diff --git a/GET_STARTED.md b/GET_STARTED.md
index 548a5e9..a793041 100644
--- a/GET_STARTED.md
+++ b/GET_STARTED.md
@@ -1,6 +1,6 @@
# Get Started
-The default hotkey for Qopy is Windows+V which is also the hotkey for the default clipboard manager to turn that off follow [this guide](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md#disable-windowsv-for-default-clipboard-manager).
+The default hotkey for Qopy is Windows+V which is also the hotkey for the default clipboard manager to turn that off follow [this guide](https://github.com/0PandaDEV/Qopy/blob/main/GET_STARTED.md#disable-windowsv-for-default-clipboard-manager).
All the data of Qopy is stored inside of a SQLite database.
@@ -12,7 +12,7 @@ All the data of Qopy is stored inside of a SQLite database.
## Disable Windows+V for default clipboard manager
-https://github.com/user-attachments/assets/723f9e07-3190-46ec-9bb7-15dfc112f620
+
To disable the default clipboard manager popup from windows open Command prompt and run this command
diff --git a/pages/settings.vue b/pages/settings.vue
index cf4771e..7a20eb1 100644
--- a/pages/settings.vue
+++ b/pages/settings.vue
@@ -33,7 +33,6 @@
@@ -44,7 +43,7 @@
class="key"
:class="{ modifier: isModifier(key) }"
v-for="(key, index) in keybind">
- {{ keyToDisplay(key) }}
+ {{ keyToLabel(key) }}
@@ -58,10 +57,11 @@ import { onMounted, onUnmounted, reactive, ref } from "vue";
import { platform } from "@tauri-apps/plugin-os";
import { useRouter } from "vue-router";
import { Key } from "wrdu-keyboard/key";
+import { KeyValues, KeyLabels } from "../types/keys";
-const activeModifiers = reactive>(new Set());
+const activeModifiers = reactive>(new Set());
const isKeybindInputFocused = ref(false);
-const keybind = ref([]);
+const keybind = ref([]);
const keybindInput = ref(null);
const lastBlurTime = ref(0);
const os = ref("");
@@ -69,52 +69,27 @@ const router = useRouter();
const keyboard = useKeyboard();
const showEmptyKeybindError = ref(false);
-const keyToDisplayMap: Record = {
- " ": "Space",
- Alt: "Alt",
- AltLeft: "Alt L",
- AltRight: "Alt R",
- ArrowDown: "↓",
- ArrowLeft: "←",
- ArrowRight: "→",
- ArrowUp: "↑",
- Control: "Ctrl",
- ControlLeft: "Ctrl L",
- ControlRight: "Ctrl R",
- Enter: "↵",
- Meta: "Meta",
- MetaLeft: "Meta L",
- MetaRight: "Meta R",
- Shift: "⇧",
- ShiftLeft: "⇧ L",
- ShiftRight: "⇧ R",
-};
-
const modifierKeySet = new Set([
- "Alt",
- "AltLeft",
- "AltRight",
- "Control",
- "ControlLeft",
- "ControlRight",
- "Meta",
- "MetaLeft",
- "MetaRight",
- "Shift",
- "ShiftLeft",
- "ShiftRight",
+ KeyValues.AltLeft,
+ KeyValues.AltRight,
+ KeyValues.ControlLeft,
+ KeyValues.ControlRight,
+ KeyValues.MetaLeft,
+ KeyValues.MetaRight,
+ KeyValues.ShiftLeft,
+ KeyValues.ShiftRight,
]);
-const isModifier = (key: string): boolean => {
+const isModifier = (key: KeyValues): boolean => {
return modifierKeySet.has(key);
};
-const keyToDisplay = (key: string): string => {
- return keyToDisplayMap[key] || key;
+const keyToLabel = (key: KeyValues): string => {
+ return KeyLabels[key] || key;
};
const updateKeybind = () => {
- const modifiers = Array.from(activeModifiers).sort();
+ const modifiers = Array.from(activeModifiers);
const nonModifiers = keybind.value.filter((key) => !isModifier(key));
keybind.value = [...modifiers, ...nonModifiers];
};
@@ -133,9 +108,9 @@ const onFocus = () => {
};
const onKeyDown = (event: KeyboardEvent) => {
- const key = event.code;
+ const key = event.code as KeyValues;
- if (key === "Escape") {
+ if (key === KeyValues.Escape) {
if (keybindInput.value) {
keybindInput.value.blur();
}
@@ -155,8 +130,7 @@ const onKeyDown = (event: KeyboardEvent) => {
const saveKeybind = async () => {
if (keybind.value.length > 0) {
- console.log("Saving keybind", keybind.value);
- await invoke("save_keybind", { keybind: keybind });
+ await invoke("save_keybind", { keybind: keybind.value });
} else {
showEmptyKeybindError.value = true;
}
@@ -165,8 +139,13 @@ const saveKeybind = async () => {
os.value = platform();
onMounted(() => {
+ keyboard.down([Key.All], (event) => {
+ if (isKeybindInputFocused.value) {
+ onKeyDown(event);
+ }
+ });
+
keyboard.down([Key.Escape], (event) => {
- console.log("Escape key pressed");
if (isKeybindInputFocused.value) {
keybindInput.value?.blur();
} else {
diff --git a/patches/wrdu-keyboard@3.0.0.patch b/patches/wrdu-keyboard@3.0.0.patch
index e973647..bc77583 100644
--- a/patches/wrdu-keyboard@3.0.0.patch
+++ b/patches/wrdu-keyboard@3.0.0.patch
@@ -1,6 +1,6 @@
diff --git a/node_modules/wrdu-keyboard/.DS_Store b/.DS_Store
new file mode 100644
-index 0000000000000000000000000000000000000000..fabbd951c2d14c46fd10fa167b8836d116bc0db6
+index 0000000000000000000000000000000000000000..4b7e9446f3580fab3e4feaba097bcdaf98c5833c
Binary files /dev/null and b/.DS_Store differ
diff --git a/dist/runtime/keyboard.d.ts b/dist/runtime/keyboard.d.ts
index aeae40f3d2bc3efd459cce04c29c21c43884154d..6131bab4895ebb3048a5225f366430d23c5f1f13 100644
@@ -27,10 +27,10 @@ index aeae40f3d2bc3efd459cce04c29c21c43884154d..6131bab4895ebb3048a5225f366430d2
up: New;
prevent: {
diff --git a/dist/runtime/keyboard.js b/dist/runtime/keyboard.js
-index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cdb37820aa 100644
+index e16f600258cee90d185ffc52777bed95c14bd93e..5ddec447a5dc66ffe063eb9f9dd765c9045bdaf7 100644
--- a/dist/runtime/keyboard.js
+++ b/dist/runtime/keyboard.js
-@@ -1,13 +1,14 @@
+@@ -1,45 +1,54 @@
import { Key } from "./types/keys.js";
import { defineNuxtPlugin } from "#app";
-const getKeyString = (keys) => keys[0] == Key.All ? keys.sort().join("+") : "All";
@@ -45,18 +45,31 @@ index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cd
+ const key = event.code;
+ pressedKeys.add(key);
const pressedArray = Array.from(pressedKeys);
- const keyString = getKeyString(pressedArray);
- if (handlers.down[keyString]) {
-@@ -17,13 +18,16 @@ const onKeydown = (event) => {
- }
- eventHandler.handler(event);
- if (eventHandler.once) {
+- const keyString = getKeyString(pressedArray);
+- if (handlers.down[keyString]) {
+- handlers.down[keyString].forEach((eventHandler) => {
+- if (eventHandler.prevent) {
+- event.preventDefault();
+- }
+- eventHandler.handler(event);
+- if (eventHandler.once) {
- handlers.down[keyString] = handlers.down[keyString].filter((h) => h !== eventHandler);
-+ handlers.down[keyString] = handlers.down[keyString].filter(
-+ (h) => h !== eventHandler
-+ );
- }
- });
+- }
+- });
++ for (const keyString of [getKeyString(pressedArray), "All"]) {
++ if (handlers.down[keyString]) {
++ handlers.down[keyString].forEach((eventHandler) => {
++ if (eventHandler.prevent) {
++ event.preventDefault();
++ }
++ eventHandler.handler(event);
++ if (eventHandler.once) {
++ handlers.down[keyString] = handlers.down[keyString].filter(
++ (h) => h !== eventHandler
++ );
++ }
++ });
++ }
}
};
const onKeyup = (event) => {
@@ -64,18 +77,31 @@ index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cd
+ const key = event.code;
+ pressedKeys.delete(key);
const releasedArray = Array.from(pressedKeys);
- const keyString = getKeyString(releasedArray);
- if (handlers.up[keyString]) {
-@@ -33,13 +37,16 @@ const onKeyup = (event) => {
- }
- eventHandler.handler(event);
- if (eventHandler.once) {
+- const keyString = getKeyString(releasedArray);
+- if (handlers.up[keyString]) {
+- handlers.up[keyString].forEach((eventHandler) => {
+- if (eventHandler.prevent) {
+- event.preventDefault();
+- }
+- eventHandler.handler(event);
+- if (eventHandler.once) {
- handlers.up[keyString] = handlers.up[keyString].filter((h) => h !== eventHandler);
-+ handlers.up[keyString] = handlers.up[keyString].filter(
-+ (h) => h !== eventHandler
-+ );
- }
- });
+- }
+- });
++ for (const keyString of [getKeyString(releasedArray), "All"]) {
++ if (handlers.up[keyString]) {
++ handlers.up[keyString].forEach((eventHandler) => {
++ if (eventHandler.prevent) {
++ event.preventDefault();
++ }
++ eventHandler.handler(event);
++ if (eventHandler.once) {
++ handlers.up[keyString] = handlers.up[keyString].filter(
++ (h) => h !== eventHandler
++ );
++ }
++ });
++ }
}
};
const init = () => {
@@ -84,36 +110,18 @@ index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cd
window.addEventListener("keydown", onKeydown);
window.addEventListener("keyup", onKeyup);
};
-@@ -47,6 +54,20 @@ const stop = () => {
+@@ -47,6 +56,10 @@ const stop = () => {
window.removeEventListener("keydown", onKeydown);
window.removeEventListener("keyup", onKeyup);
};
+const unregisterAll = () => {
-+ Object.keys(handlers.down).forEach((key) => {
-+ handlers.down[key].forEach((handler) => {
-+ console.log(`Unregistering ${key} ${handler.handler.toString()}`);
-+ });
-+ });
-+ Object.keys(handlers.up).forEach((key) => {
-+ handlers.up[key].forEach((handler) => {
-+ console.log(`Unregistering ${key} ${handler.handler.toString()}`);
-+ });
-+ });
+ handlers.down = {};
+ handlers.up = {};
+};
const down = (keys, handler, config = {}) => {
if (keys.includes(Key.All)) {
keys = [Key.All];
-@@ -59,6 +80,7 @@ const down = (keys, handler, config = {}) => {
- handlers.down[key] = [];
- }
- const { once = false, prevent = false } = config;
-+ console.log(key, handler.toString());
- handlers.down[key].push({ handler, prevent, once });
- };
- const up = (keys, handler, config = {}) => {
-@@ -84,6 +106,7 @@ const keyboard = defineNuxtPlugin((nuxtApp) => {
+@@ -84,6 +97,7 @@ const keyboard = defineNuxtPlugin((nuxtApp) => {
keyboard: {
init,
stop,
diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs
index 0470e24..52a276b 100644
--- a/src-tauri/src/api/hotkeys.rs
+++ b/src-tauri/src/api/hotkeys.rs
@@ -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> = RefCell::new(None);
+lazy_static! {
+ static ref HOTKEY_MANAGER: Mutex > = Mutex::new(None);
+ static ref REGISTERED_HOTKEYS: Mutex> = 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::();
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 = 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 = 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> {
+fn register_shortcut(shortcut: &[String]) -> Result<(), Box> {
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> {
+fn parse_hotkey(shortcut: &[String]) -> Result> {
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" }
+ })),
+ );
}
diff --git a/src-tauri/src/db/settings.rs b/src-tauri/src/db/settings.rs
index bdd6f58..7fedf8c 100644
--- a/src-tauri/src/db/settings.rs
+++ b/src-tauri/src/db/settings.rs
@@ -30,11 +30,8 @@ pub async fn save_keybind(
pool: tauri::State<'_, SqlitePool>,
keybind: Vec,
) -> Result<(), String> {
- let keybind_str = keybind.join("+");
- let keybind_clone = keybind_str.clone();
-
app_handle
- .emit("update-shortcut", &keybind_str)
+ .emit("update-shortcut", &keybind)
.map_err(|e| e.to_string())?;
let json = serde_json::to_string(&keybind).map_err(|e| e.to_string())?;
@@ -46,7 +43,7 @@ pub async fn save_keybind(
.map_err(|e| e.to_string())?;
let _ = app_handle.track_event("keybind_saved", Some(serde_json::json!({
- "keybind": keybind_clone
+ "keybind": keybind
})));
Ok(())
@@ -97,7 +94,7 @@ pub async fn get_keybind(app_handle: tauri::AppHandle) -> Result, St
.map_err(|e| e.to_string())?;
let json = row.map(|r| r.get::("value")).unwrap_or_else(|| {
- serde_json::to_string(&vec!["Meta".to_string(), "V".to_string()])
+ serde_json::to_string(&vec!["MetaLeft".to_string(), "KeyV".to_string()])
.expect("Failed to serialize default keybind")
});
diff --git a/src-tauri/src/utils/keys.rs b/src-tauri/src/utils/keys.rs
new file mode 100644
index 0000000..fffacdd
--- /dev/null
+++ b/src-tauri/src/utils/keys.rs
@@ -0,0 +1,118 @@
+use global_hotkey::hotkey::Code;
+use std::str::FromStr;
+
+pub struct KeyCode(Code);
+
+impl FromStr for KeyCode {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result {
+ let code = match s {
+ "Backquote" => Code::Backquote,
+ "Backslash" => Code::Backslash,
+ "BracketLeft" => Code::BracketLeft,
+ "BracketRight" => Code::BracketRight,
+ "Comma" => Code::Comma,
+ "Digit0" => Code::Digit0,
+ "Digit1" => Code::Digit1,
+ "Digit2" => Code::Digit2,
+ "Digit3" => Code::Digit3,
+ "Digit4" => Code::Digit4,
+ "Digit5" => Code::Digit5,
+ "Digit6" => Code::Digit6,
+ "Digit7" => Code::Digit7,
+ "Digit8" => Code::Digit8,
+ "Digit9" => Code::Digit9,
+ "Equal" => Code::Equal,
+ "KeyA" => Code::KeyA,
+ "KeyB" => Code::KeyB,
+ "KeyC" => Code::KeyC,
+ "KeyD" => Code::KeyD,
+ "KeyE" => Code::KeyE,
+ "KeyF" => Code::KeyF,
+ "KeyG" => Code::KeyG,
+ "KeyH" => Code::KeyH,
+ "KeyI" => Code::KeyI,
+ "KeyJ" => Code::KeyJ,
+ "KeyK" => Code::KeyK,
+ "KeyL" => Code::KeyL,
+ "KeyM" => Code::KeyM,
+ "KeyN" => Code::KeyN,
+ "KeyO" => Code::KeyO,
+ "KeyP" => Code::KeyP,
+ "KeyQ" => Code::KeyQ,
+ "KeyR" => Code::KeyR,
+ "KeyS" => Code::KeyS,
+ "KeyT" => Code::KeyT,
+ "KeyU" => Code::KeyU,
+ "KeyV" => Code::KeyV,
+ "KeyW" => Code::KeyW,
+ "KeyX" => Code::KeyX,
+ "KeyY" => Code::KeyY,
+ "KeyZ" => Code::KeyZ,
+ "Minus" => Code::Minus,
+ "Period" => Code::Period,
+ "Quote" => Code::Quote,
+ "Semicolon" => Code::Semicolon,
+ "Slash" => Code::Slash,
+ "Backspace" => Code::Backspace,
+ "CapsLock" => Code::CapsLock,
+ "Delete" => Code::Delete,
+ "Enter" => Code::Enter,
+ "Space" => Code::Space,
+ "Tab" => Code::Tab,
+ "End" => Code::End,
+ "Home" => Code::Home,
+ "Insert" => Code::Insert,
+ "PageDown" => Code::PageDown,
+ "PageUp" => Code::PageUp,
+ "ArrowDown" => Code::ArrowDown,
+ "ArrowLeft" => Code::ArrowLeft,
+ "ArrowRight" => Code::ArrowRight,
+ "ArrowUp" => Code::ArrowUp,
+ "NumLock" => Code::NumLock,
+ "Numpad0" => Code::Numpad0,
+ "Numpad1" => Code::Numpad1,
+ "Numpad2" => Code::Numpad2,
+ "Numpad3" => Code::Numpad3,
+ "Numpad4" => Code::Numpad4,
+ "Numpad5" => Code::Numpad5,
+ "Numpad6" => Code::Numpad6,
+ "Numpad7" => Code::Numpad7,
+ "Numpad8" => Code::Numpad8,
+ "Numpad9" => Code::Numpad9,
+ "NumpadAdd" => Code::NumpadAdd,
+ "NumpadDecimal" => Code::NumpadDecimal,
+ "NumpadDivide" => Code::NumpadDivide,
+ "NumpadMultiply" => Code::NumpadMultiply,
+ "NumpadSubtract" => Code::NumpadSubtract,
+ "Escape" => Code::Escape,
+ "PrintScreen" => Code::PrintScreen,
+ "ScrollLock" => Code::ScrollLock,
+ "Pause" => Code::Pause,
+ "AudioVolumeDown" => Code::AudioVolumeDown,
+ "AudioVolumeMute" => Code::AudioVolumeMute,
+ "AudioVolumeUp" => Code::AudioVolumeUp,
+ "F1" => Code::F1,
+ "F2" => Code::F2,
+ "F3" => Code::F3,
+ "F4" => Code::F4,
+ "F5" => Code::F5,
+ "F6" => Code::F6,
+ "F7" => Code::F7,
+ "F8" => Code::F8,
+ "F9" => Code::F9,
+ "F10" => Code::F10,
+ "F11" => Code::F11,
+ "F12" => Code::F12,
+ _ => return Err(format!("Unknown key code: {}", s)),
+ };
+ Ok(KeyCode(code))
+ }
+}
+
+impl From for Code {
+ fn from(key_code: KeyCode) -> Self {
+ key_code.0
+ }
+}
diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs
index b888b1f..9554229 100644
--- a/src-tauri/src/utils/mod.rs
+++ b/src-tauri/src/utils/mod.rs
@@ -2,3 +2,4 @@ pub mod commands;
pub mod favicon;
pub mod types;
pub mod logger;
+pub mod keys;
\ No newline at end of file
diff --git a/types/keys.ts b/types/keys.ts
new file mode 100644
index 0000000..d81454f
--- /dev/null
+++ b/types/keys.ts
@@ -0,0 +1,217 @@
+export enum KeyValues {
+ Backquote = 'Backquote',
+ Backslash = 'Backslash',
+ BracketLeft = 'BracketLeft',
+ BracketRight = 'BracketRight',
+ Comma = 'Comma',
+ Digit0 = 'Digit0',
+ Digit1 = 'Digit1',
+ Digit2 = 'Digit2',
+ Digit3 = 'Digit3',
+ Digit4 = 'Digit4',
+ Digit5 = 'Digit5',
+ Digit6 = 'Digit6',
+ Digit7 = 'Digit7',
+ Digit8 = 'Digit8',
+ Digit9 = 'Digit9',
+ Equal = 'Equal',
+ KeyA = 'KeyA',
+ KeyB = 'KeyB',
+ KeyC = 'KeyC',
+ KeyD = 'KeyD',
+ KeyE = 'KeyE',
+ KeyF = 'KeyF',
+ KeyG = 'KeyG',
+ KeyH = 'KeyH',
+ KeyI = 'KeyI',
+ KeyJ = 'KeyJ',
+ KeyK = 'KeyK',
+ KeyL = 'KeyL',
+ KeyM = 'KeyM',
+ KeyN = 'KeyN',
+ KeyO = 'KeyO',
+ KeyP = 'KeyP',
+ KeyQ = 'KeyQ',
+ KeyR = 'KeyR',
+ KeyS = 'KeyS',
+ KeyT = 'KeyT',
+ KeyU = 'KeyU',
+ KeyV = 'KeyV',
+ KeyW = 'KeyW',
+ KeyX = 'KeyX',
+ KeyY = 'KeyY',
+ KeyZ = 'KeyZ',
+ Minus = 'Minus',
+ Period = 'Period',
+ Quote = 'Quote',
+ Semicolon = 'Semicolon',
+ Slash = 'Slash',
+ AltLeft = 'AltLeft',
+ AltRight = 'AltRight',
+ Backspace = 'Backspace',
+ CapsLock = 'CapsLock',
+ ContextMenu = 'ContextMenu',
+ ControlLeft = 'ControlLeft',
+ ControlRight = 'ControlRight',
+ Enter = 'Enter',
+ MetaLeft = 'MetaLeft',
+ MetaRight = 'MetaRight',
+ ShiftLeft = 'ShiftLeft',
+ ShiftRight = 'ShiftRight',
+ Space = 'Space',
+ Tab = 'Tab',
+ Delete = 'Delete',
+ End = 'End',
+ Home = 'Home',
+ Insert = 'Insert',
+ PageDown = 'PageDown',
+ PageUp = 'PageUp',
+ ArrowDown = 'ArrowDown',
+ ArrowLeft = 'ArrowLeft',
+ ArrowRight = 'ArrowRight',
+ ArrowUp = 'ArrowUp',
+ NumLock = 'NumLock',
+ Numpad0 = 'Numpad0',
+ Numpad1 = 'Numpad1',
+ Numpad2 = 'Numpad2',
+ Numpad3 = 'Numpad3',
+ Numpad4 = 'Numpad4',
+ Numpad5 = 'Numpad5',
+ Numpad6 = 'Numpad6',
+ Numpad7 = 'Numpad7',
+ Numpad8 = 'Numpad8',
+ Numpad9 = 'Numpad9',
+ NumpadAdd = 'NumpadAdd',
+ NumpadDecimal = 'NumpadDecimal',
+ NumpadDivide = 'NumpadDivide',
+ NumpadMultiply = 'NumpadMultiply',
+ NumpadSubtract = 'NumpadSubtract',
+ Escape = 'Escape',
+ PrintScreen = 'PrintScreen',
+ ScrollLock = 'ScrollLock',
+ Pause = 'Pause',
+ AudioVolumeDown = 'AudioVolumeDown',
+ AudioVolumeMute = 'AudioVolumeMute',
+ AudioVolumeUp = 'AudioVolumeUp',
+ F1 = 'F1',
+ F2 = 'F2',
+ F3 = 'F3',
+ F4 = 'F4',
+ F5 = 'F5',
+ F6 = 'F6',
+ F7 = 'F7',
+ F8 = 'F8',
+ F9 = 'F9',
+ F10 = 'F10',
+ F11 = 'F11',
+ F12 = 'F12',
+}
+
+export enum KeyLabels {
+ Backquote = '`',
+ Backslash = '\\',
+ BracketLeft = '[',
+ BracketRight = ']',
+ Comma = ',',
+ Digit0 = '0',
+ Digit1 = '1',
+ Digit2 = '2',
+ Digit3 = '3',
+ Digit4 = '4',
+ Digit5 = '5',
+ Digit6 = '6',
+ Digit7 = '7',
+ Digit8 = '8',
+ Digit9 = '9',
+ Equal = '=',
+ KeyA = 'A',
+ KeyB = 'B',
+ KeyC = 'C',
+ KeyD = 'D',
+ KeyE = 'E',
+ KeyF = 'F',
+ KeyG = 'G',
+ KeyH = 'H',
+ KeyI = 'I',
+ KeyJ = 'J',
+ KeyK = 'K',
+ KeyL = 'L',
+ KeyM = 'M',
+ KeyN = 'N',
+ KeyO = 'O',
+ KeyP = 'P',
+ KeyQ = 'Q',
+ KeyR = 'R',
+ KeyS = 'S',
+ KeyT = 'T',
+ KeyU = 'U',
+ KeyV = 'V',
+ KeyW = 'W',
+ KeyX = 'X',
+ KeyY = 'Y',
+ KeyZ = 'Z',
+ Minus = '-',
+ Period = '.',
+ Quote = "'",
+ Semicolon = ';',
+ Slash = '/',
+ AltLeft = 'Alt',
+ AltRight = 'Alt (Right)',
+ Backspace = 'Backspace',
+ CapsLock = 'Caps Lock',
+ ContextMenu = 'Context Menu',
+ ControlLeft = 'Ctrl',
+ ControlRight = 'Ctrl (Right)',
+ Enter = 'Enter',
+ MetaLeft = 'Meta',
+ MetaRight = 'Meta (Right)',
+ ShiftLeft = 'Shift',
+ ShiftRight = 'Shift (Right)',
+ Space = 'Space',
+ Tab = 'Tab',
+ Delete = 'Delete',
+ End = 'End',
+ Home = 'Home',
+ Insert = 'Insert',
+ PageDown = 'Page Down',
+ PageUp = 'Page Up',
+ ArrowDown = '↓',
+ ArrowLeft = '←',
+ ArrowRight = '→',
+ ArrowUp = '↑',
+ NumLock = 'Num Lock',
+ Numpad0 = 'Numpad 0',
+ Numpad1 = 'Numpad 1',
+ Numpad2 = 'Numpad 2',
+ Numpad3 = 'Numpad 3',
+ Numpad4 = 'Numpad 4',
+ Numpad5 = 'Numpad 5',
+ Numpad6 = 'Numpad 6',
+ Numpad7 = 'Numpad 7',
+ Numpad8 = 'Numpad 8',
+ Numpad9 = 'Numpad 9',
+ NumpadAdd = 'Numpad +',
+ NumpadDecimal = 'Numpad .',
+ NumpadDivide = 'Numpad /',
+ NumpadMultiply = 'Numpad *',
+ NumpadSubtract = 'Numpad -',
+ Escape = 'Esc',
+ PrintScreen = 'Print Screen',
+ ScrollLock = 'Scroll Lock',
+ Pause = 'Pause',
+ AudioVolumeDown = 'Volume Down',
+ AudioVolumeMute = 'Volume Mute',
+ AudioVolumeUp = 'Volume Up',
+ F1 = 'F1',
+ F2 = 'F2',
+ F3 = 'F3',
+ F4 = 'F4',
+ F5 = 'F5',
+ F6 = 'F6',
+ F7 = 'F7',
+ F8 = 'F8',
+ F9 = 'F9',
+ F10 = 'F10',
+ F11 = 'F11',
+ F12 = 'F12',
+}
\ No newline at end of file