shortcuts dev...

This commit is contained in:
Gabe Yuan
2023-09-07 18:12:45 +08:00
parent da13f5e218
commit d8b0cc4834
8 changed files with 11006 additions and 15315 deletions

View File

@@ -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",

View File

@@ -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`,
},
};

View File

@@ -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
View 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 };
}

View File

@@ -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;
};

View File

@@ -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]);

View File

@@ -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>

26100
yarn.lock

File diff suppressed because it is too large Load Diff