fix: parse hotkey (#5167)

* fix: incorrectly parse hotkey

* refactor: parse hotkey

* fix: panic on linux

* chore: update

* chore: update style

* fix: register hotkey error on windows

* chore: update style

---------

Co-authored-by: Tunglies <tunglies.dev@outlook.com>
This commit is contained in:
oomeow
2025-10-23 15:54:48 +08:00
committed by GitHub
parent 585963e751
commit d7859b07a6
6 changed files with 25 additions and 80 deletions

View File

@@ -38,8 +38,9 @@
- 启用 TUN 前等待服务就绪
- 卸载 TUN 时会先关闭
- 优化应用启动页
- 优化首页当前节点对 MATCH 规则的支持
- 优化首页当前节点对MATCH规则的支持
- 允许在 `界面设置` 修改 `悬浮跳转导航延迟`
- 添加热键绑定错误的提示信息
### 🐞 修复问题
@@ -69,6 +70,7 @@
- 修复自动更新使版本回退的问题
- 修复首页自定义卡片在切换轻量模式时失效
- 修复悬浮跳转导航失效
- 修复小键盘热键映射错误
## v2.4.2

View File

@@ -1,8 +1,8 @@
use crate::process::AsyncHandler;
use crate::utils::notification::{NotificationEvent, notify_event};
use crate::{
config::Config, core::handle, feat, logging, logging_error,
module::lightweight::entry_lightweight_mode, singleton_with_logging, utils::logging::Type,
config::Config, core::handle, feat, logging, module::lightweight::entry_lightweight_mode,
singleton_with_logging, utils::logging::Type,
};
use anyhow::{Result, bail};
use parking_lot::Mutex;
@@ -224,7 +224,7 @@ impl Hotkey {
let is_quit = matches!(function, HotkeyFunction::Quit);
let _ = manager.on_shortcut(hotkey, move |app_handle, hotkey_event, event| {
manager.on_shortcut(hotkey, move |app_handle, hotkey_event, event| {
let hotkey_event_owned = *hotkey_event;
let event_owned = event;
let function_owned = function;
@@ -271,7 +271,7 @@ impl Hotkey {
}
}
});
});
})?;
logging!(
debug,
@@ -402,7 +402,7 @@ impl Hotkey {
});
for (key, func) in add.iter() {
logging_error!(Type::Hotkey, self.register(key, func).await);
self.register(key, func).await?;
}
// Update the current hotkeys after all async operations

View File

@@ -676,7 +676,14 @@ async fn create_tray_menu(
.filter_map(|item| {
let mut parts = item.split(',');
match (parts.next(), parts.next()) {
(Some(func), Some(key)) => Some((func.into(), key.into())),
(Some(func), Some(key)) => {
// 托盘菜单中的 `accelerator` 属性,在 Linux/Windows 中都不支持小键盘按键的解析
if key.to_uppercase().contains("NUMPAD") {
None
} else {
Some((func.into(), key.into()))
}
}
_ => None,
}
})

View File

@@ -7,7 +7,7 @@ import { parseHotkey } from "@/utils/parse-hotkey";
const KeyWrapper = styled("div")(({ theme }) => ({
position: "relative",
width: 165,
width: 230,
minHeight: 36,
"> input": {
@@ -39,6 +39,7 @@ const KeyWrapper = styled("div")(({ theme }) => ({
},
},
".item": {
fontSize: "14px",
color: theme.palette.text.primary,
border: "1px solid",
borderColor: alpha(theme.palette.text.secondary, 0.2),
@@ -76,11 +77,10 @@ export const HotkeyInput = (props: Props) => {
}
}}
onKeyDown={(e) => {
const evt = e.nativeEvent;
e.preventDefault();
e.stopPropagation();
const key = parseHotkey(evt.key);
const key = parseHotkey(e);
if (key === "UNIDENTIFIED") return;
changeRef.current = [...new Set([...changeRef.current, key])];

View File

@@ -82,7 +82,7 @@ export const HotkeyViewer = forwardRef<DialogRef>((props, ref) => {
});
setOpen(false);
} catch (err: any) {
showNotice("error", err.toString());
showNotice("error", err.message || err.toString());
}
});

View File

@@ -1,26 +1,6 @@
import { KeyboardEvent } from "react";
const KEY_MAP: Record<string, string> = {
// 特殊字符映射
"-": "Minus",
"=": "Equal",
"[": "BracketLeft",
"]": "BracketRight",
"\\": "Backslash",
";": "Semicolon",
"'": "Quote",
",": "Comma",
".": "Period",
"/": "Slash",
// 数字键映射
"1": "Digit1",
"2": "Digit2",
"3": "Digit3",
"4": "Digit4",
"5": "Digit5",
"6": "Digit6",
"7": "Digit7",
"8": "Digit8",
"9": "Digit9",
"0": "Digit0",
// Option + 特殊字符映射
"": "Minus", // Option + -
"≠": "Equal", // Option + =
@@ -66,55 +46,11 @@ const mapKeyCombination = (key: string): string => {
const mappedKey = KEY_MAP[key] || key;
return `${mappedKey}`;
};
export const parseHotkey = (key: string) => {
export const parseHotkey = (keyEvent: KeyboardEvent) => {
const nativeEvent = keyEvent.nativeEvent;
const key = nativeEvent.code;
let temp = key.toUpperCase();
// 处理特殊符号到键位的映射
switch (temp) {
// 数字键符号
case "!":
return "DIGIT1"; // shift + 1
case "@":
return "DIGIT2"; // shift + 2
case "#":
return "DIGIT3"; // shift + 3
case "$":
return "DIGIT4"; // shift + 4
case "%":
return "DIGIT5"; // shift + 5
case "^":
return "DIGIT6"; // shift + 6
case "&":
return "DIGIT7"; // shift + 7
case "*":
return "DIGIT8"; // shift + 8
case "(":
return "DIGIT9"; // shift + 9
case ")":
return "DIGIT0"; // shift + 0
// 其他特殊符号
case "?":
return "SLASH"; // shift + /
case ":":
return "SEMICOLON"; // shift + ;
case "+":
return "EQUAL"; // shift + =
case "_":
return "MINUS"; // shift + -
case '"':
return "QUOTE"; // shift + '
case "<":
return "COMMA"; // shift + ,
case ">":
return "PERIOD"; // shift + .
case "{":
return "BRACKETLEFT"; // shift + [
case "}":
return "BRACKETRIGHT"; // shift + ]
case "|":
return "BACKSLASH"; // shift + \
}
if (temp.startsWith("ARROW")) {
temp = temp.slice(5);
} else if (temp.startsWith("DIGIT")) {