Skip to content

Commit

Permalink
refactor: replace lazy_static with OnceCell for hotkey manager and re…
Browse files Browse the repository at this point in the history
…gistered hotkey
  • Loading branch information
0PandaDEV committed Jan 10, 2025
1 parent 416e2f0 commit 42aa72f
Showing 1 changed file with 53 additions and 54 deletions.
107 changes: 53 additions & 54 deletions src-tauri/src/api/hotkeys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ use global_hotkey::{
GlobalHotKeyManager,
HotKeyState,
};
use lazy_static::lazy_static;
use std::str::FromStr;
use std::sync::Mutex;
use tauri::{ AppHandle, Listener, Manager };
use tauri::{ AppHandle, Manager, Listener };
use tauri_plugin_aptabase::EventTracker;
use tokio::sync::OnceCell;

lazy_static! {
static ref HOTKEY_MANAGER: Mutex<Option<GlobalHotKeyManager>> = Mutex::new(None);
static ref REGISTERED_HOTKEY: Mutex<Option<HotKey>> = Mutex::new(None);
}
static HOTKEY_MANAGER: OnceCell<Mutex<Option<GlobalHotKeyManager>>> = OnceCell::const_new();
static REGISTERED_HOTKEY: OnceCell<Mutex<Option<HotKey>>> = OnceCell::const_new();

pub fn setup(app_handle: tauri::AppHandle) {
let app_handle_clone = app_handle.clone();
let _ = HOTKEY_MANAGER.set(Mutex::new(None));
let _ = REGISTERED_HOTKEY.set(Mutex::new(None));

let app_handle_clone = app_handle.clone();
let manager = match GlobalHotKeyManager::new() {
Ok(manager) => manager,
Err(err) => {
Expand All @@ -28,8 +28,8 @@ pub fn setup(app_handle: tauri::AppHandle) {
}
};

{
let mut manager_guard = HOTKEY_MANAGER.lock().unwrap();
if let Some(hotkey_manager) = HOTKEY_MANAGER.get() {
let mut manager_guard = hotkey_manager.lock().unwrap();
*manager_guard = Some(manager);
}

Expand All @@ -42,66 +42,75 @@ pub fn setup(app_handle: tauri::AppHandle) {
eprintln!("Error registering initial shortcut: {:?}", e);
}

setup_event_listeners(&app_handle);
setup_hotkey_receiver(app_handle);
}

fn setup_event_listeners(app_handle: &AppHandle) {
app_handle.listen("update-shortcut", move |event| {
let payload_str = event.payload().replace("\\\"", "\"");
let trimmed_str = payload_str.trim_matches('"');

if let Some(old_hotkey) = REGISTERED_HOTKEY.lock().unwrap().take() {
let manager_guard = HOTKEY_MANAGER.lock().unwrap();
if let Some(manager) = manager_guard.as_ref() {
let _ = manager.unregister(old_hotkey);
}
}

unregister_current_hotkey();

let payload: Vec<String> = serde_json::from_str(trimmed_str).unwrap_or_default();

if let Err(e) = register_shortcut(&payload) {
eprintln!("Error re-registering shortcut: {:?}", e);
}
});

app_handle.listen("save_keybind", move |event| {
let payload_str = event.payload().to_string();

if let Some(old_hotkey) = REGISTERED_HOTKEY.lock().unwrap().take() {
let manager_guard = HOTKEY_MANAGER.lock().unwrap();
if let Some(manager) = manager_guard.as_ref() {
let _ = manager.unregister(old_hotkey);
}
}

unregister_current_hotkey();

let payload: Vec<String> = serde_json::from_str(&payload_str).unwrap_or_default();
if let Err(e) = register_shortcut(&payload) {
eprintln!("Error registering saved shortcut: {:?}", e);
}
});
}

let app_handle_for_hotkey = app_handle.clone();
fn setup_hotkey_receiver(app_handle: AppHandle) {
tauri::async_runtime::spawn(async move {
loop {
match GlobalHotKeyEvent::receiver().recv() {
Ok(event) => {
if event.state == HotKeyState::Released {
continue;
}
handle_hotkey_event(&app_handle_for_hotkey);
}
Err(e) => {
eprintln!("Error receiving hotkey event: {:?}", e);
handle_hotkey_event(&app_handle);
}
Err(e) => eprintln!("Error receiving hotkey event: {:?}", e),
}
}
});
}

fn unregister_current_hotkey() {
if let Some(registered) = REGISTERED_HOTKEY.get() {
if let Some(old_hotkey) = registered.lock().unwrap().take() {
if let Some(manager) = HOTKEY_MANAGER.get() {
if let Some(manager) = manager.lock().unwrap().as_ref() {
let _ = manager.unregister(old_hotkey);
}
}
}
}
}

fn register_shortcut(shortcut: &[String]) -> Result<(), Box<dyn std::error::Error>> {
let hotkey = parse_hotkey(shortcut)?;

let manager_guard = HOTKEY_MANAGER.lock().unwrap();
if let Some(manager) = manager_guard.as_ref() {
manager.register(hotkey.clone())?;
*REGISTERED_HOTKEY.lock().unwrap() = Some(hotkey);
Ok(())
if let Some(manager) = HOTKEY_MANAGER.get() {
let manager_guard = manager.lock().unwrap();
if let Some(manager) = manager_guard.as_ref() {
manager.register(hotkey.clone())?;
if let Some(registered) = REGISTERED_HOTKEY.get() {
*registered.lock().unwrap() = Some(hotkey);
}
Ok(())
} else {
Err("Hotkey manager not initialized".into())
}
} else {
Err("Hotkey manager not initialized".into())
}
Expand All @@ -113,21 +122,11 @@ fn parse_hotkey(shortcut: &[String]) -> Result<HotKey, Box<dyn std::error::Error

for part in shortcut {
match part.as_str() {
"ControlLeft" => {
modifiers |= Modifiers::CONTROL;
}
"AltLeft" => {
modifiers |= Modifiers::ALT;
}
"ShiftLeft" => {
modifiers |= Modifiers::SHIFT;
}
"MetaLeft" => {
modifiers |= Modifiers::META;
}
key => {
code = Some(Code::from(KeyCode::from_str(key)?));
}
"ControlLeft" => modifiers |= Modifiers::CONTROL,
"AltLeft" => modifiers |= Modifiers::ALT,
"ShiftLeft" => modifiers |= Modifiers::SHIFT,
"MetaLeft" => modifiers |= Modifiers::META,
key => code = Some(Code::from(KeyCode::from_str(key)?)),
}
}

Expand Down Expand Up @@ -157,8 +156,8 @@ fn handle_hotkey_event(app_handle: &AppHandle) {
"hotkey_triggered",
Some(
serde_json::json!({
"action": if window.is_visible().unwrap() { "hide" } else { "show" }
})
"action": if window.is_visible().unwrap() { "hide" } else { "show" }
})
)
);
}
}

0 comments on commit 42aa72f

Please sign in to comment.