mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-01-31 00:45:24 +01:00
refactor(global-shortcut): enhance un/register to accept an array, remove un/registerAll (#1117)
* refactor(shell): enhance `un/register` to accept an array, remove `un/registerAll` closes #1101 * Update lib.rs * remove permissions, cleanup docs * bring back unregister_all * fmt * fix build * bundle --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
10
.changes/global-shortcut-js-apis-refactor.md
Normal file
10
.changes/global-shortcut-js-apis-refactor.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
"global-shortcut": "patch"
|
||||
---
|
||||
|
||||
Refactored the Rust APIs:
|
||||
|
||||
- Renamed `GlobalShortcut::on_all_shortcuts` to `GlobalShortcut::on_shortcuts`
|
||||
- Renamed `GlobalShortcut::register_all` to `GlobalShortcut::register_multiple`
|
||||
- Changed `GlobalShortcut::unregister_all` behavior to remove all registerd shortcuts.
|
||||
- Added `GlobalShortcut::unregister_multiple` to register a list of shortcuts (old behavior of `unregister_all`).
|
||||
8
.changes/global-shortcut-rust-apis-refactor.md
Normal file
8
.changes/global-shortcut-rust-apis-refactor.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"global-shortcut-js": "patch"
|
||||
---
|
||||
|
||||
Refactored the JS APIs:
|
||||
|
||||
- Enhanced `register` and `unregister` to take either a single shortcut or an array.
|
||||
- Removed `registerAll` instead use `register` with an array.
|
||||
@@ -4850,13 +4850,6 @@
|
||||
"global-shortcut:allow-register"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "global-shortcut:allow-register-all -> Enables the register_all command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"global-shortcut:allow-register-all"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "global-shortcut:allow-unregister -> Enables the unregister command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -4885,13 +4878,6 @@
|
||||
"global-shortcut:deny-register"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "global-shortcut:deny-register-all -> Denies the register_all command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"global-shortcut:deny-register-all"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "global-shortcut:deny-unregister -> Denies the unregister command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<script>
|
||||
import { writable } from "svelte/store";
|
||||
import { writable, get } from "svelte/store";
|
||||
import {
|
||||
register as registerShortcut,
|
||||
unregister as unregisterShortcut,
|
||||
unregisterAll as unregisterAllShortcuts,
|
||||
} from "@tauri-apps/plugin-global-shortcut";
|
||||
|
||||
export let onMessage;
|
||||
@@ -35,7 +34,7 @@
|
||||
}
|
||||
|
||||
function unregisterAll() {
|
||||
unregisterAllShortcuts()
|
||||
unregisterShortcut(get(shortcuts))
|
||||
.then(() => {
|
||||
shortcuts.update(() => []);
|
||||
onMessage(`Unregistered all shortcuts`);
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBALSHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("a"===r&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,n){if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,n,i;"function"==typeof SuppressedError&&SuppressedError;class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),n.set(this,0),i.set(this,{}),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o===e(this,n,"f")){r(this,n,o+1),e(this,s,"f").call(this,t);const a=Object.keys(e(this,i,"f"));if(a.length>0){let t=o+1;for(const r of a.sort()){if(parseInt(r)!==t)break;{const n=e(this,i,"f")[r];delete e(this,i,"f")[r],e(this,s,"f").call(this,n),t+=1}}r(this,n,t)}}else e(this,i,"f")[o.toString()]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}async function a(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return s=new WeakMap,n=new WeakMap,i=new WeakMap,t.isRegistered=async function(t){return await a("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new o;r.onmessage=e,await a("plugin:global-shortcut|register",{shortcut:t,handler:r})},t.registerAll=async function(t,e){const r=new o;r.onmessage=e,await a("plugin:global-shortcut|register_all",{shortcuts:t,handler:r})},t.unregister=async function(t){await a("plugin:global-shortcut|unregister",{shortcut:t})},t.unregisterAll=async function(){await a("plugin:global-shortcut|unregister_all")},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBALSHORTCUT__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBALSHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("a"===r&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,n){if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,n,i;"function"==typeof SuppressedError&&SuppressedError;class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),n.set(this,0),i.set(this,{}),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o===e(this,n,"f")){r(this,n,o+1),e(this,s,"f").call(this,t);const a=Object.keys(e(this,i,"f"));if(a.length>0){let t=o+1;for(const r of a.sort()){if(parseInt(r)!==t)break;{const n=e(this,i,"f")[r];delete e(this,i,"f")[r],e(this,s,"f").call(this,n),t+=1}}r(this,n,t)}}else e(this,i,"f")[o.toString()]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}async function a(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return s=new WeakMap,n=new WeakMap,i=new WeakMap,t.isRegistered=async function(t){return await a("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new o;return r.onmessage=e,await a("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:r})},t.unregister=async function(t){return await a("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await a("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBALSHORTCUT__})}
|
||||
|
||||
@@ -2,13 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const COMMANDS: &[&str] = &[
|
||||
"register",
|
||||
"register_all",
|
||||
"unregister",
|
||||
"unregister_all",
|
||||
"is_registered",
|
||||
];
|
||||
const COMMANDS: &[&str] = &["register", "unregister", "unregister_all", "is_registered"];
|
||||
|
||||
fn main() {
|
||||
tauri_plugin::Builder::new(COMMANDS)
|
||||
|
||||
@@ -19,15 +19,28 @@ export interface ShortcutEvent {
|
||||
export type ShortcutHandler = (event: ShortcutEvent) => void;
|
||||
|
||||
/**
|
||||
* Register a global shortcut.
|
||||
* Register a global shortcut or a list of shortcuts.
|
||||
*
|
||||
* The handler is called when any of the registered shortcuts are pressed by the user.
|
||||
*
|
||||
* If the shortcut is already taken by another application, the handler will not be triggered.
|
||||
* Make sure the shortcut is as unique as possible while still taking user experience into consideration.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { register } from '@tauri-apps/plugin-global-shortcut';
|
||||
*
|
||||
* // register a single hotkey
|
||||
* await register('CommandOrControl+Shift+C', (event) => {
|
||||
* if (event.state === "Pressed") {
|
||||
* console.log('Shortcut triggered');
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // or register multiple hotkeys at once
|
||||
* await register(['CommandOrControl+Shift+C', 'Alt+A'], (event) => {
|
||||
* console.log(`Shortcut ${event.shortcut} triggered`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param shortcut Shortcut definition, modifiers and key separated by "+" e.g. CmdOrControl+Q
|
||||
@@ -36,46 +49,56 @@ export type ShortcutHandler = (event: ShortcutEvent) => void;
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function register(
|
||||
shortcut: string,
|
||||
shortcuts: string | string[],
|
||||
handler: ShortcutHandler,
|
||||
): Promise<void> {
|
||||
const h = new Channel<ShortcutEvent>();
|
||||
h.onmessage = handler;
|
||||
|
||||
await invoke("plugin:global-shortcut|register", {
|
||||
shortcut,
|
||||
return await invoke("plugin:global-shortcut|register", {
|
||||
shortcuts: Array.isArray(shortcuts) ? shortcuts : [shortcuts],
|
||||
handler: h,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a collection of global shortcuts.
|
||||
* Unregister a global shortcut or a list of shortcuts.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { registerAll } from '@tauri-apps/plugin-global-shortcut';
|
||||
* await registerAll(['CommandOrControl+Shift+C', 'Ctrl+Alt+F12'], (event) => {
|
||||
* console.log(`Shortcut ${event.shortcut} ${event.state}`);
|
||||
* });
|
||||
* import { unregister } from '@tauri-apps/plugin-global-shortcut';
|
||||
*
|
||||
* // unregister a single hotkey
|
||||
* await unregister('CmdOrControl+Space');
|
||||
*
|
||||
* // or unregister multiple hotkeys at the same time
|
||||
* await unregister(['CmdOrControl+Space', 'Alt+A']);
|
||||
* ```
|
||||
*
|
||||
* @param shortcuts Array of shortcut definitions, modifiers and key separated by "+" e.g. CmdOrControl+Q
|
||||
* @param handler Shortcut handler callback - takes the triggered shortcut as argument
|
||||
* @param shortcut shortcut definition (modifiers and key separated by "+" e.g. CmdOrControl+Q), also accepts a list of shortcuts
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function registerAll(
|
||||
shortcuts: string[],
|
||||
handler: ShortcutHandler,
|
||||
): Promise<void> {
|
||||
const h = new Channel<ShortcutEvent>();
|
||||
h.onmessage = handler;
|
||||
|
||||
await invoke("plugin:global-shortcut|register_all", {
|
||||
shortcuts,
|
||||
handler: h,
|
||||
async function unregister(shortcuts: string | string[]): Promise<void> {
|
||||
return await invoke("plugin:global-shortcut|unregister", {
|
||||
shortcuts: Array.isArray(shortcuts) ? shortcuts : [shortcuts],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister all global shortcuts.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { unregisterAll } from '@tauri-apps/plugin-global-shortcut';
|
||||
* await unregisterAll();
|
||||
* ```
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function unregisterAll(): Promise<void> {
|
||||
return await invoke("plugin:global-shortcut|unregister_all", {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given shortcut is registered by this application or not.
|
||||
*
|
||||
@@ -97,36 +120,4 @@ async function isRegistered(shortcut: string): Promise<boolean> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a global shortcut.
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { unregister } from '@tauri-apps/plugin-global-shortcut';
|
||||
* await unregister('CmdOrControl+Space');
|
||||
* ```
|
||||
*
|
||||
* @param shortcut shortcut definition, modifiers and key separated by "+" e.g. CmdOrControl+Q
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function unregister(shortcut: string): Promise<void> {
|
||||
await invoke("plugin:global-shortcut|unregister", {
|
||||
shortcut,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all shortcuts registered by the application.
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { unregisterAll } from '@tauri-apps/plugin-global-shortcut';
|
||||
* await unregisterAll();
|
||||
* ```
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function unregisterAll(): Promise<void> {
|
||||
await invoke("plugin:global-shortcut|unregister_all");
|
||||
}
|
||||
|
||||
export { register, registerAll, isRegistered, unregister, unregisterAll };
|
||||
export { register, unregister, unregisterAll, isRegistered };
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[default]
|
||||
description = """
|
||||
No features are enabled by default, as we believe
|
||||
the shortcuts can be inherently dangerous and it is
|
||||
the shortcuts can be inherently dangerous and it is
|
||||
application specific if specific shortcuts should be
|
||||
registered or unregistered.
|
||||
"""
|
||||
|
||||
@@ -29,7 +29,7 @@ use serde::Serialize;
|
||||
use tauri::{
|
||||
ipc::Channel,
|
||||
plugin::{Builder as PluginBuilder, TauriPlugin},
|
||||
AppHandle, Manager, Runtime, State, Window,
|
||||
AppHandle, Manager, Runtime, State,
|
||||
};
|
||||
|
||||
mod error;
|
||||
@@ -84,7 +84,7 @@ impl<R: Runtime> GlobalShortcut<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn register_all_internal<S, F>(&self, shortcuts: S, handler: Option<F>) -> Result<()>
|
||||
fn register_multiple_internal<S, F>(&self, shortcuts: S, handler: Option<F>) -> Result<()>
|
||||
where
|
||||
S: IntoIterator<Item = Shortcut>,
|
||||
F: Fn(&AppHandle<R>, &Shortcut, ShortcutEvent) + Send + Sync + 'static,
|
||||
@@ -107,7 +107,9 @@ impl<R: Runtime> GlobalShortcut<R> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> GlobalShortcut<R> {
|
||||
/// Register a shortcut.
|
||||
pub fn register<S>(&self, shortcut: S) -> Result<()>
|
||||
where
|
||||
@@ -131,7 +133,7 @@ impl<R: Runtime> GlobalShortcut<R> {
|
||||
}
|
||||
|
||||
/// Register multiple shortcuts.
|
||||
pub fn register_all<S, T>(&self, shortcuts: S) -> Result<()>
|
||||
pub fn register_multiple<S, T>(&self, shortcuts: S) -> Result<()>
|
||||
where
|
||||
S: IntoIterator<Item = T>,
|
||||
T: TryInto<ShortcutWrapper>,
|
||||
@@ -141,11 +143,11 @@ impl<R: Runtime> GlobalShortcut<R> {
|
||||
for shortcut in shortcuts {
|
||||
s.push(try_into_shortcut(shortcut)?);
|
||||
}
|
||||
self.register_all_internal(s, None::<fn(&AppHandle<R>, &Shortcut, ShortcutEvent)>)
|
||||
self.register_multiple_internal(s, None::<fn(&AppHandle<R>, &Shortcut, ShortcutEvent)>)
|
||||
}
|
||||
|
||||
/// Register multiple shortcuts with a handler.
|
||||
pub fn on_all_shortcuts<S, T, F>(&self, shortcuts: S, handler: F) -> Result<()>
|
||||
pub fn on_shortcuts<S, T, F>(&self, shortcuts: S, handler: F) -> Result<()>
|
||||
where
|
||||
S: IntoIterator<Item = T>,
|
||||
T: TryInto<ShortcutWrapper>,
|
||||
@@ -156,9 +158,10 @@ impl<R: Runtime> GlobalShortcut<R> {
|
||||
for shortcut in shortcuts {
|
||||
s.push(try_into_shortcut(shortcut)?);
|
||||
}
|
||||
self.register_all_internal(s, Some(handler))
|
||||
self.register_multiple_internal(s, Some(handler))
|
||||
}
|
||||
|
||||
/// Unregister a shortcut
|
||||
pub fn unregister<S: TryInto<ShortcutWrapper>>(&self, shortcut: S) -> Result<()>
|
||||
where
|
||||
S::Error: std::error::Error,
|
||||
@@ -169,7 +172,8 @@ impl<R: Runtime> GlobalShortcut<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister_all<T: TryInto<ShortcutWrapper>, S: IntoIterator<Item = T>>(
|
||||
/// Unregister multiple shortcuts.
|
||||
pub fn unregister_multiple<T: TryInto<ShortcutWrapper>, S: IntoIterator<Item = T>>(
|
||||
&self,
|
||||
shortcuts: S,
|
||||
) -> Result<()>
|
||||
@@ -191,6 +195,16 @@ impl<R: Runtime> GlobalShortcut<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unregister all registered shortcuts.
|
||||
pub fn unregister_all(&self) -> Result<()> {
|
||||
let mut shortcuts = self.shortcuts.lock().unwrap();
|
||||
let hotkeys = std::mem::take(&mut *shortcuts);
|
||||
let hotkeys = hotkeys.values().map(|s| s.shortcut).collect::<Vec<_>>();
|
||||
self.manager
|
||||
.unregister_all(hotkeys.as_slice())
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Determines whether the given shortcut is registered by this application or not.
|
||||
///
|
||||
/// If the shortcut is registered by another application, it will still return `false`.
|
||||
@@ -239,29 +253,7 @@ struct ShortcutJsEvent {
|
||||
|
||||
#[tauri::command]
|
||||
fn register<R: Runtime>(
|
||||
_window: Window<R>,
|
||||
global_shortcut: State<'_, GlobalShortcut<R>>,
|
||||
shortcut: String,
|
||||
handler: Channel,
|
||||
) -> Result<()> {
|
||||
global_shortcut.register_internal(
|
||||
parse_shortcut(shortcut)?,
|
||||
Some(
|
||||
move |_app: &AppHandle<R>, shortcut: &Shortcut, e: ShortcutEvent| {
|
||||
let js_event = ShortcutJsEvent {
|
||||
id: e.id,
|
||||
state: e.state,
|
||||
shortcut: shortcut.into_string(),
|
||||
};
|
||||
let _ = handler.send(js_event);
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn register_all<R: Runtime>(
|
||||
_window: Window<R>,
|
||||
_app: AppHandle<R>,
|
||||
global_shortcut: State<'_, GlobalShortcut<R>>,
|
||||
shortcuts: Vec<String>,
|
||||
handler: Channel,
|
||||
@@ -275,7 +267,7 @@ fn register_all<R: Runtime>(
|
||||
hotkeys.push(hotkey);
|
||||
}
|
||||
|
||||
global_shortcut.register_all_internal(
|
||||
global_shortcut.register_multiple_internal(
|
||||
hotkeys,
|
||||
Some(
|
||||
move |_app: &AppHandle<R>, shortcut: &Shortcut, e: ShortcutEvent| {
|
||||
@@ -292,15 +284,6 @@ fn register_all<R: Runtime>(
|
||||
|
||||
#[tauri::command]
|
||||
fn unregister<R: Runtime>(
|
||||
_app: AppHandle<R>,
|
||||
global_shortcut: State<'_, GlobalShortcut<R>>,
|
||||
shortcut: String,
|
||||
) -> Result<()> {
|
||||
global_shortcut.unregister(parse_shortcut(shortcut)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn unregister_all<R: Runtime>(
|
||||
_app: AppHandle<R>,
|
||||
global_shortcut: State<'_, GlobalShortcut<R>>,
|
||||
shortcuts: Vec<String>,
|
||||
@@ -309,7 +292,15 @@ fn unregister_all<R: Runtime>(
|
||||
for shortcut in shortcuts {
|
||||
hotkeys.push(parse_shortcut(&shortcut)?);
|
||||
}
|
||||
global_shortcut.unregister_all(hotkeys)
|
||||
global_shortcut.unregister_multiple(hotkeys)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn unregister_all<R: Runtime>(
|
||||
_app: AppHandle<R>,
|
||||
global_shortcut: State<'_, GlobalShortcut<R>>,
|
||||
) -> Result<()> {
|
||||
global_shortcut.unregister_all()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -379,10 +370,9 @@ impl<R: Runtime> Builder<R> {
|
||||
PluginBuilder::new("global-shortcut")
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
register,
|
||||
register_all,
|
||||
unregister,
|
||||
unregister_all,
|
||||
is_registered
|
||||
is_registered,
|
||||
])
|
||||
.setup(move |app, _api| {
|
||||
let manager = GlobalHotKeyManager::new()?;
|
||||
|
||||
Reference in New Issue
Block a user