mirror of
https://github.com/0PandaDEV/Qopy.git
synced 2025-04-21 21:24:05 +02:00
refactor: improve keybind saving logic and error handling
This commit is contained in:
parent
6656af8ab1
commit
0c28a5b0db
8 changed files with 478 additions and 154 deletions
|
@ -1,48 +1,61 @@
|
|||
use tauri_plugin_aptabase::EventTracker;
|
||||
use crate::utils::commands::center_window_on_current_monitor;
|
||||
use crate::utils::keys::KeyCode;
|
||||
use global_hotkey::{
|
||||
hotkey::{Code, HotKey, Modifiers},
|
||||
GlobalHotKeyEvent, GlobalHotKeyManager, HotKeyState,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use lazy_static::lazy_static;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Mutex;
|
||||
use tauri::{AppHandle, Listener, Manager};
|
||||
use tauri_plugin_aptabase::EventTracker;
|
||||
|
||||
thread_local! {
|
||||
static HOTKEY_MANAGER: RefCell<Option<GlobalHotKeyManager>> = RefCell::new(None);
|
||||
lazy_static! {
|
||||
static ref HOTKEY_MANAGER: Mutex<Option<GlobalHotKeyManager>> = Mutex::new(None);
|
||||
static ref REGISTERED_HOTKEYS: Mutex<Vec<HotKey>> = Mutex::new(Vec::new());
|
||||
}
|
||||
|
||||
pub fn setup(app_handle: tauri::AppHandle) {
|
||||
let app_handle_clone = app_handle.clone();
|
||||
|
||||
let manager = GlobalHotKeyManager::new().expect("Failed to initialize hotkey manager");
|
||||
HOTKEY_MANAGER.with(|m| *m.borrow_mut() = Some(manager));
|
||||
let manager = match GlobalHotKeyManager::new() {
|
||||
Ok(manager) => manager,
|
||||
Err(err) => {
|
||||
eprintln!("Failed to initialize hotkey manager: {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
let mut manager_guard = HOTKEY_MANAGER.lock().unwrap();
|
||||
*manager_guard = Some(manager);
|
||||
}
|
||||
|
||||
let rt = app_handle.state::<tokio::runtime::Runtime>();
|
||||
let initial_keybind = rt
|
||||
.block_on(crate::db::settings::get_keybind(app_handle_clone.clone()))
|
||||
.expect("Failed to get initial keybind");
|
||||
let initial_shortcut = initial_keybind.join("+");
|
||||
|
||||
let initial_shortcut_for_update = initial_shortcut.clone();
|
||||
let initial_shortcut_for_save = initial_shortcut.clone();
|
||||
let initial_shortcut_for_update = initial_keybind.clone();
|
||||
let initial_shortcut_for_save = initial_keybind.clone();
|
||||
|
||||
if let Err(e) = register_shortcut(&initial_shortcut) {
|
||||
if let Err(e) = register_shortcut(&initial_keybind) {
|
||||
eprintln!("Error registering initial shortcut: {:?}", e);
|
||||
}
|
||||
|
||||
app_handle.listen("update-shortcut", move |event| {
|
||||
let payload_str = event.payload().to_string();
|
||||
let payload_str = event.payload();
|
||||
|
||||
if let Ok(old_hotkey) = parse_hotkey(&initial_shortcut_for_update) {
|
||||
HOTKEY_MANAGER.with(|manager| {
|
||||
if let Some(manager) = manager.borrow().as_ref() {
|
||||
let _ = manager.unregister(old_hotkey);
|
||||
}
|
||||
});
|
||||
let manager_guard = HOTKEY_MANAGER.lock().unwrap();
|
||||
if let Some(manager) = manager_guard.as_ref() {
|
||||
let _ = manager.unregister(old_hotkey);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = register_shortcut(&payload_str) {
|
||||
let payload: Vec<String> = serde_json::from_str(payload_str).unwrap_or_default();
|
||||
|
||||
if let Err(e) = register_shortcut(&payload) {
|
||||
eprintln!("Error re-registering shortcut: {:?}", e);
|
||||
}
|
||||
});
|
||||
|
@ -51,14 +64,14 @@ pub fn setup(app_handle: tauri::AppHandle) {
|
|||
let payload_str = event.payload().to_string();
|
||||
|
||||
if let Ok(old_hotkey) = parse_hotkey(&initial_shortcut_for_save) {
|
||||
HOTKEY_MANAGER.with(|manager| {
|
||||
if let Some(manager) = manager.borrow().as_ref() {
|
||||
let _ = manager.unregister(old_hotkey);
|
||||
}
|
||||
});
|
||||
let manager_guard = HOTKEY_MANAGER.lock().unwrap();
|
||||
if let Some(manager) = manager_guard.as_ref() {
|
||||
let _ = manager.unregister(old_hotkey);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = register_shortcut(&payload_str) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
@ -81,48 +94,36 @@ pub fn setup(app_handle: tauri::AppHandle) {
|
|||
});
|
||||
}
|
||||
|
||||
fn register_shortcut(shortcut: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||
fn register_shortcut(shortcut: &[String]) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let hotkey = parse_hotkey(shortcut)?;
|
||||
HOTKEY_MANAGER.with(|manager| {
|
||||
if let Some(manager) = manager.borrow().as_ref() {
|
||||
manager.register(hotkey)?;
|
||||
}
|
||||
|
||||
let manager_guard = HOTKEY_MANAGER.lock().unwrap();
|
||||
if let Some(manager) = manager_guard.as_ref() {
|
||||
manager.register(hotkey.clone())?;
|
||||
REGISTERED_HOTKEYS.lock().unwrap().push(hotkey);
|
||||
Ok(())
|
||||
})
|
||||
} else {
|
||||
Err("Hotkey manager not initialized".into())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_hotkey(shortcut: &str) -> Result<HotKey, Box<dyn std::error::Error>> {
|
||||
fn parse_hotkey(shortcut: &[String]) -> Result<HotKey, Box<dyn std::error::Error>> {
|
||||
let mut modifiers = Modifiers::empty();
|
||||
let mut code = None;
|
||||
|
||||
let shortcut = shortcut.replace("\"", "");
|
||||
|
||||
for part in shortcut.split('+') {
|
||||
let part = part.trim().to_lowercase();
|
||||
for part in shortcut {
|
||||
match part.as_str() {
|
||||
"ctrl" | "control" | "controlleft" => modifiers |= Modifiers::CONTROL,
|
||||
"alt" | "altleft" | "optionleft" => modifiers |= Modifiers::ALT,
|
||||
"shift" | "shiftleft" => modifiers |= Modifiers::SHIFT,
|
||||
"super" | "meta" | "cmd" | "metaleft" => modifiers |= Modifiers::META,
|
||||
"ControlLeft" => modifiers |= Modifiers::CONTROL,
|
||||
"AltLeft" => modifiers |= Modifiers::ALT,
|
||||
"ShiftLeft" => modifiers |= Modifiers::SHIFT,
|
||||
"MetaLeft" => modifiers |= Modifiers::META,
|
||||
key => {
|
||||
let key_code = if key.starts_with("key") {
|
||||
"Key".to_string() + &key[3..].to_uppercase()
|
||||
} else if key.len() == 1 && key.chars().next().unwrap().is_alphabetic() {
|
||||
"Key".to_string() + &key.to_uppercase()
|
||||
} else {
|
||||
key.to_string()
|
||||
};
|
||||
|
||||
code = Some(
|
||||
Code::from_str(&key_code)
|
||||
.map_err(|_| format!("Invalid key code: {}", key_code))?,
|
||||
);
|
||||
code = Some(Code::from(KeyCode::from_str(key)?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let key_code =
|
||||
code.ok_or_else(|| format!("No valid key code found in shortcut: {}", shortcut))?;
|
||||
let key_code = code.ok_or_else(|| "No valid key code found".to_string())?;
|
||||
Ok(HotKey::new(Some(modifiers), key_code))
|
||||
}
|
||||
|
||||
|
@ -144,7 +145,10 @@ fn handle_hotkey_event(app_handle: &AppHandle) {
|
|||
center_window_on_current_monitor(&window);
|
||||
}
|
||||
|
||||
let _ = app_handle.track_event("hotkey_triggered", Some(serde_json::json!({
|
||||
"action": if window.is_visible().unwrap() { "hide" } else { "show" }
|
||||
})));
|
||||
let _ = app_handle.track_event(
|
||||
"hotkey_triggered",
|
||||
Some(serde_json::json!({
|
||||
"action": if window.is_visible().unwrap() { "hide" } else { "show" }
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue