shortcuts dev...
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
"@emotion/styled": "^11.10.8",
|
||||
"@mui/icons-material": "^5.11.11",
|
||||
"@mui/material": "^5.11.12",
|
||||
"@violentmonkey/shortcut": "^1.3.0",
|
||||
"query-string": "^8.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
||||
@@ -489,4 +489,20 @@ export const I18N = {
|
||||
zh: `恢复默认`,
|
||||
en: `Restore Default`,
|
||||
},
|
||||
shortcuts_setting: {
|
||||
zh: `快捷键设置`,
|
||||
en: `Shortcuts Setting`,
|
||||
},
|
||||
toggle_translate_shortcut: {
|
||||
zh: `开启翻译快捷键`,
|
||||
en: `Toggle Translate Shortcut`,
|
||||
},
|
||||
toggle_style_shortcut: {
|
||||
zh: `切换样式快捷键`,
|
||||
en: `Toggle Style Shortcut`,
|
||||
},
|
||||
toggle_popup_shortcut: {
|
||||
zh: `打开弹窗快捷键`,
|
||||
en: `Open Popup Shortcut`,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -238,6 +238,16 @@ export const DEFAULT_TRANS_APIS = {
|
||||
},
|
||||
};
|
||||
|
||||
// 默认快捷键
|
||||
export const OPT_SHORTCUT_TRANSLATE = "toggleTranslate";
|
||||
export const OPT_SHORTCUT_STYLE = "toggleStyle";
|
||||
export const OPT_SHORTCUT_POPUP = "togglePopup";
|
||||
export const DEFAULT_SHORTCUTS = {
|
||||
[OPT_SHORTCUT_TRANSLATE]: ["Alt", "q"],
|
||||
[OPT_SHORTCUT_STYLE]: ["Alt", "c"],
|
||||
[OPT_SHORTCUT_POPUP]: ["Alt", "k"],
|
||||
};
|
||||
|
||||
export const TRANS_MIN_LENGTH = 5; // 最短翻译长度
|
||||
export const TRANS_MAX_LENGTH = 5000; // 最长翻译长度
|
||||
export const TRANS_NEWLINE_LENGTH = 40; // 换行字符数
|
||||
@@ -256,6 +266,7 @@ export const DEFAULT_SETTING = {
|
||||
owSubrule: DEFAULT_OW_RULE, // 覆写订阅规则
|
||||
transApis: DEFAULT_TRANS_APIS, // 翻译接口
|
||||
mouseKey: OPT_MOUSEKEY_DISABLE, // 鼠标悬停翻译
|
||||
shortcuts: DEFAULT_SHORTCUTS, // 快捷键
|
||||
};
|
||||
|
||||
export const DEFAULT_RULES = [GLOBLA_RULE];
|
||||
|
||||
22
src/hooks/Shortcut.js
Normal file
22
src/hooks/Shortcut.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useCallback } from "react";
|
||||
import { DEFAULT_SHORTCUTS } from "../config";
|
||||
import { useSetting } from "./Setting";
|
||||
|
||||
export function useShortcut(action) {
|
||||
const { setting, updateSetting } = useSetting();
|
||||
const shortcuts = setting?.shortcuts || DEFAULT_SHORTCUTS;
|
||||
|
||||
const setShortcut = useCallback(
|
||||
async (val) => {
|
||||
await updateSetting({
|
||||
shortcuts: {
|
||||
...shortcuts,
|
||||
[action]: val,
|
||||
},
|
||||
});
|
||||
},
|
||||
[action, shortcuts, updateSetting]
|
||||
);
|
||||
|
||||
return { shortcut: shortcuts[action] || [], setShortcut };
|
||||
}
|
||||
@@ -139,3 +139,14 @@ export const sha256 = async (text, salt) => {
|
||||
* @returns
|
||||
*/
|
||||
export const genEventName = () => btoa(Math.random()).slice(3, 11);
|
||||
|
||||
/**
|
||||
* 判断两个 Set 是否相同
|
||||
* @param {*} a
|
||||
* @param {*} b
|
||||
* @returns
|
||||
*/
|
||||
export const isSameSet = (a, b) => {
|
||||
const s = new Set([...a, ...b]);
|
||||
return s.size === a.size && s.size === b.size;
|
||||
};
|
||||
|
||||
@@ -6,10 +6,10 @@ import Draggable from "./Draggable";
|
||||
import { useEffect, useState, useMemo, useCallback } from "react";
|
||||
import { SettingProvider } from "../../hooks/Setting";
|
||||
import Popup from "../Popup";
|
||||
import { debounce } from "../../libs/utils";
|
||||
import * as shortcut from "@violentmonkey/shortcut";
|
||||
import { debounce, isSameSet } from "../../libs/utils";
|
||||
import { isGm } from "../../libs/client";
|
||||
import Header from "../Popup/Header";
|
||||
import { DEFAULT_SHORTCUTS, OPT_SHORTCUT_TRANSLATE } from "../../config";
|
||||
|
||||
export default function Action({ translator, fab }) {
|
||||
const fabWidth = 40;
|
||||
@@ -43,22 +43,55 @@ export default function Action({ translator, fab }) {
|
||||
setMoved(true);
|
||||
}, []);
|
||||
|
||||
// useEffect(() => {
|
||||
// // 注册快捷键
|
||||
// const handleKeydown = (e) => {
|
||||
// if (!e.altKey) {
|
||||
// return;
|
||||
// }
|
||||
// if (e.code === "KeyQ") {
|
||||
// translator.toggle();
|
||||
// setShowPopup(false);
|
||||
// } else if (e.code === "KeyC") {
|
||||
// translator.toggleStyle();
|
||||
// setShowPopup(false);
|
||||
// } else if (e.code === "KeyK") {
|
||||
// setShowPopup((pre) => !pre);
|
||||
// }
|
||||
// };
|
||||
// window.addEventListener("keydown", handleKeydown);
|
||||
// return () => {
|
||||
// window.removeEventListener("keydown", handleKeydown);
|
||||
// };
|
||||
// }, [translator]);
|
||||
|
||||
useEffect(() => {
|
||||
// 注册快捷键
|
||||
shortcut.register("a-q", () => {
|
||||
translator.toggle();
|
||||
setShowPopup(false);
|
||||
});
|
||||
shortcut.register("a-c", () => {
|
||||
translator.toggleStyle();
|
||||
setShowPopup(false);
|
||||
});
|
||||
shortcut.register("a-k", () => {
|
||||
setShowPopup((pre) => !pre);
|
||||
});
|
||||
const shortcuts = translator.setting.shortcuts || DEFAULT_SHORTCUTS;
|
||||
const keys = new Set();
|
||||
|
||||
const handleKeydown = (e) => {
|
||||
console.log("keydown", e);
|
||||
e.code && keys.add(e.key);
|
||||
|
||||
console.log("keys", keys);
|
||||
const isSame = isSameSet(
|
||||
keys,
|
||||
new Set(shortcuts[OPT_SHORTCUT_TRANSLATE])
|
||||
);
|
||||
console.log("isSame", keys, isSame);
|
||||
};
|
||||
|
||||
const handleKeyup = (e) => {
|
||||
console.log("keyup", e);
|
||||
keys.delete(e.key);
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeydown);
|
||||
window.addEventListener("keyup", handleKeyup);
|
||||
return () => {
|
||||
shortcut.disable();
|
||||
window.removeEventListener("keydown", handleKeydown);
|
||||
window.removeEventListener("keyup", handleKeyup);
|
||||
};
|
||||
}, [translator]);
|
||||
|
||||
|
||||
@@ -12,13 +12,89 @@ import { limitNumber } from "../../libs/utils";
|
||||
import { useI18n } from "../../hooks/I18n";
|
||||
import { useAlert } from "../../hooks/Alert";
|
||||
import { isExt } from "../../libs/client";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import {
|
||||
UI_LANGS,
|
||||
TRANS_NEWLINE_LENGTH,
|
||||
CACHE_NAME,
|
||||
OPT_MOUSEKEY_ALL,
|
||||
OPT_MOUSEKEY_DISABLE,
|
||||
OPT_SHORTCUT_TRANSLATE,
|
||||
OPT_SHORTCUT_STYLE,
|
||||
OPT_SHORTCUT_POPUP,
|
||||
} from "../../config";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import { useShortcut } from "../../hooks/Shortcut";
|
||||
|
||||
function ShortcutItem({ action, label }) {
|
||||
const { shortcut, setShortcut } = useShortcut(action);
|
||||
const [disabled, setDisabled] = useState(true);
|
||||
const [focused, setFocus] = useState(false);
|
||||
const [formval, setFormval] = useState(shortcut);
|
||||
const inputRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!disabled) {
|
||||
inputRef.current.focus();
|
||||
setFormval([]);
|
||||
}
|
||||
}, [disabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!focused) {
|
||||
return;
|
||||
}
|
||||
|
||||
const keys = new Set();
|
||||
const handleKeydown = (e) => {
|
||||
// console.log("keydown", e);
|
||||
e.code && keys.add(e.key);
|
||||
setFormval([...keys]);
|
||||
};
|
||||
const handleKeyup = (e) => {
|
||||
// console.log("keyup", e);
|
||||
keys.delete(e.key);
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeydown);
|
||||
window.addEventListener("keyup", handleKeyup);
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeydown);
|
||||
window.removeEventListener("keyup", handleKeyup);
|
||||
};
|
||||
}, [focused]);
|
||||
|
||||
return (
|
||||
<Stack direction="row">
|
||||
<TextField
|
||||
size="small"
|
||||
label={label}
|
||||
name={label}
|
||||
value={formval.join(" + ")}
|
||||
fullWidth
|
||||
inputRef={inputRef}
|
||||
disabled={disabled}
|
||||
onFocus={(e) => {
|
||||
setFocus(true);
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
setFocus(false);
|
||||
setDisabled(true);
|
||||
setShortcut(formval);
|
||||
}}
|
||||
/>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setDisabled(false);
|
||||
}}
|
||||
>
|
||||
{<EditIcon />}
|
||||
</IconButton>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Settings() {
|
||||
const i18n = useI18n();
|
||||
@@ -151,7 +227,7 @@ export default function Settings() {
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
{isExt && (
|
||||
{isExt ? (
|
||||
<FormControl size="small">
|
||||
<InputLabel>{i18n("if_clear_cache")}</InputLabel>
|
||||
<Select
|
||||
@@ -169,6 +245,27 @@ export default function Settings() {
|
||||
</Link>
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
) : (
|
||||
<Grid container rowSpacing={2} columns={12}>
|
||||
<Grid item xs={12} sm={12} md={4} lg={4}>
|
||||
<ShortcutItem
|
||||
action={OPT_SHORTCUT_TRANSLATE}
|
||||
label={i18n("toggle_translate_shortcut")}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} md={4} lg={4}>
|
||||
<ShortcutItem
|
||||
action={OPT_SHORTCUT_STYLE}
|
||||
label={i18n("toggle_style_shortcut")}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} md={4} lg={4}>
|
||||
<ShortcutItem
|
||||
action={OPT_SHORTCUT_POPUP}
|
||||
label={i18n("toggle_popup_shortcut")}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user