mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 08:45:41 +08:00
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:
@@ -40,6 +40,7 @@
|
|||||||
- 优化应用启动页
|
- 优化应用启动页
|
||||||
- 优化首页当前节点对MATCH规则的支持
|
- 优化首页当前节点对MATCH规则的支持
|
||||||
- 允许在 `界面设置` 修改 `悬浮跳转导航延迟`
|
- 允许在 `界面设置` 修改 `悬浮跳转导航延迟`
|
||||||
|
- 添加热键绑定错误的提示信息
|
||||||
|
|
||||||
### 🐞 修复问题
|
### 🐞 修复问题
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@
|
|||||||
- 修复自动更新使版本回退的问题
|
- 修复自动更新使版本回退的问题
|
||||||
- 修复首页自定义卡片在切换轻量模式时失效
|
- 修复首页自定义卡片在切换轻量模式时失效
|
||||||
- 修复悬浮跳转导航失效
|
- 修复悬浮跳转导航失效
|
||||||
|
- 修复小键盘热键映射错误
|
||||||
|
|
||||||
## v2.4.2
|
## v2.4.2
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::process::AsyncHandler;
|
use crate::process::AsyncHandler;
|
||||||
use crate::utils::notification::{NotificationEvent, notify_event};
|
use crate::utils::notification::{NotificationEvent, notify_event};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config, core::handle, feat, logging, logging_error,
|
config::Config, core::handle, feat, logging, module::lightweight::entry_lightweight_mode,
|
||||||
module::lightweight::entry_lightweight_mode, singleton_with_logging, utils::logging::Type,
|
singleton_with_logging, utils::logging::Type,
|
||||||
};
|
};
|
||||||
use anyhow::{Result, bail};
|
use anyhow::{Result, bail};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -224,7 +224,7 @@ impl Hotkey {
|
|||||||
|
|
||||||
let is_quit = matches!(function, HotkeyFunction::Quit);
|
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 hotkey_event_owned = *hotkey_event;
|
||||||
let event_owned = event;
|
let event_owned = event;
|
||||||
let function_owned = function;
|
let function_owned = function;
|
||||||
@@ -271,7 +271,7 @@ impl Hotkey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
})?;
|
||||||
|
|
||||||
logging!(
|
logging!(
|
||||||
debug,
|
debug,
|
||||||
@@ -402,7 +402,7 @@ impl Hotkey {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (key, func) in add.iter() {
|
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
|
// Update the current hotkeys after all async operations
|
||||||
|
|||||||
@@ -676,7 +676,14 @@ async fn create_tray_menu(
|
|||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
let mut parts = item.split(',');
|
let mut parts = item.split(',');
|
||||||
match (parts.next(), parts.next()) {
|
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,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { parseHotkey } from "@/utils/parse-hotkey";
|
|||||||
|
|
||||||
const KeyWrapper = styled("div")(({ theme }) => ({
|
const KeyWrapper = styled("div")(({ theme }) => ({
|
||||||
position: "relative",
|
position: "relative",
|
||||||
width: 165,
|
width: 230,
|
||||||
minHeight: 36,
|
minHeight: 36,
|
||||||
|
|
||||||
"> input": {
|
"> input": {
|
||||||
@@ -39,6 +39,7 @@ const KeyWrapper = styled("div")(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
".item": {
|
".item": {
|
||||||
|
fontSize: "14px",
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
border: "1px solid",
|
border: "1px solid",
|
||||||
borderColor: alpha(theme.palette.text.secondary, 0.2),
|
borderColor: alpha(theme.palette.text.secondary, 0.2),
|
||||||
@@ -76,11 +77,10 @@ export const HotkeyInput = (props: Props) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
const evt = e.nativeEvent;
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
const key = parseHotkey(evt.key);
|
const key = parseHotkey(e);
|
||||||
if (key === "UNIDENTIFIED") return;
|
if (key === "UNIDENTIFIED") return;
|
||||||
|
|
||||||
changeRef.current = [...new Set([...changeRef.current, key])];
|
changeRef.current = [...new Set([...changeRef.current, key])];
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export const HotkeyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
});
|
});
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
showNotice("error", err.toString());
|
showNotice("error", err.message || err.toString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,6 @@
|
|||||||
|
import { KeyboardEvent } from "react";
|
||||||
|
|
||||||
const KEY_MAP: Record<string, string> = {
|
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 + 特殊字符映射
|
// Option + 特殊字符映射
|
||||||
"–": "Minus", // Option + -
|
"–": "Minus", // Option + -
|
||||||
"≠": "Equal", // Option + =
|
"≠": "Equal", // Option + =
|
||||||
@@ -66,55 +46,11 @@ const mapKeyCombination = (key: string): string => {
|
|||||||
const mappedKey = KEY_MAP[key] || key;
|
const mappedKey = KEY_MAP[key] || key;
|
||||||
return `${mappedKey}`;
|
return `${mappedKey}`;
|
||||||
};
|
};
|
||||||
export const parseHotkey = (key: string) => {
|
export const parseHotkey = (keyEvent: KeyboardEvent) => {
|
||||||
|
const nativeEvent = keyEvent.nativeEvent;
|
||||||
|
const key = nativeEvent.code;
|
||||||
let temp = key.toUpperCase();
|
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")) {
|
if (temp.startsWith("ARROW")) {
|
||||||
temp = temp.slice(5);
|
temp = temp.slice(5);
|
||||||
} else if (temp.startsWith("DIGIT")) {
|
} else if (temp.startsWith("DIGIT")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user