shortcuts dev
This commit is contained in:
@@ -494,15 +494,15 @@ export const I18N = {
|
|||||||
en: `Shortcuts Setting`,
|
en: `Shortcuts Setting`,
|
||||||
},
|
},
|
||||||
toggle_translate_shortcut: {
|
toggle_translate_shortcut: {
|
||||||
zh: `开启翻译快捷键`,
|
zh: `"开启翻译"快捷键`,
|
||||||
en: `Toggle Translate Shortcut`,
|
en: `"Toggle Translate" Shortcut`,
|
||||||
},
|
},
|
||||||
toggle_style_shortcut: {
|
toggle_style_shortcut: {
|
||||||
zh: `切换样式快捷键`,
|
zh: `"切换样式"快捷键`,
|
||||||
en: `Toggle Style Shortcut`,
|
en: `"Toggle Style" Shortcut`,
|
||||||
},
|
},
|
||||||
toggle_popup_shortcut: {
|
toggle_popup_shortcut: {
|
||||||
zh: `打开弹窗快捷键`,
|
zh: `"打开弹窗"快捷键`,
|
||||||
en: `Open Popup Shortcut`,
|
en: `"Open Popup" Shortcut`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,21 +4,21 @@ import { useSetting } from "./Setting";
|
|||||||
|
|
||||||
export function useApi(translator) {
|
export function useApi(translator) {
|
||||||
const { setting, updateSetting } = useSetting();
|
const { setting, updateSetting } = useSetting();
|
||||||
const apis = setting?.transApis || DEFAULT_TRANS_APIS;
|
const transApis = setting?.transApis || DEFAULT_TRANS_APIS;
|
||||||
|
|
||||||
const updateApi = useCallback(
|
const updateApi = useCallback(
|
||||||
async (obj) => {
|
async (obj) => {
|
||||||
const api = apis[translator] || {};
|
const api = transApis[translator] || {};
|
||||||
const transApis = { ...apis, [translator]: { ...api, ...obj } };
|
Object.assign(transApis, { [translator]: { ...api, ...obj } });
|
||||||
await updateSetting({ transApis });
|
await updateSetting({ transApis });
|
||||||
},
|
},
|
||||||
[translator, apis, updateSetting]
|
[translator, transApis, updateSetting]
|
||||||
);
|
);
|
||||||
|
|
||||||
const resetApi = useCallback(async () => {
|
const resetApi = useCallback(async () => {
|
||||||
const transApis = { ...apis, [translator]: DEFAULT_TRANS_APIS[translator] };
|
Object.assign(transApis, { [translator]: DEFAULT_TRANS_APIS[translator] });
|
||||||
await updateSetting({ transApis });
|
await updateSetting({ transApis });
|
||||||
}, [translator, apis, updateSetting]);
|
}, [translator, transApis, updateSetting]);
|
||||||
|
|
||||||
return { api: apis[translator] || {}, updateApi, resetApi };
|
return { api: transApis[translator] || {}, updateApi, resetApi };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,8 @@ export function useShortcut(action) {
|
|||||||
|
|
||||||
const setShortcut = useCallback(
|
const setShortcut = useCallback(
|
||||||
async (val) => {
|
async (val) => {
|
||||||
await updateSetting({
|
Object.assign(shortcuts, { [action]: val });
|
||||||
shortcuts: {
|
await updateSetting({ shortcuts });
|
||||||
...shortcuts,
|
|
||||||
[action]: val,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[action, shortcuts, updateSetting]
|
[action, shortcuts, updateSetting]
|
||||||
);
|
);
|
||||||
|
|||||||
49
src/libs/shortcut.js
Normal file
49
src/libs/shortcut.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import { isSameSet } from "./utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 键盘快捷键监听
|
||||||
|
* @param {*} fn
|
||||||
|
* @param {*} target
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const shortcutListener = (fn, target = document) => {
|
||||||
|
const allkeys = new Set();
|
||||||
|
const curkeys = new Set();
|
||||||
|
|
||||||
|
const handleKeydown = (e) => {
|
||||||
|
if (e.code) {
|
||||||
|
allkeys.add(e.key);
|
||||||
|
curkeys.add(e.key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyup = (e) => {
|
||||||
|
curkeys.delete(e.key);
|
||||||
|
if (curkeys.size === 0) {
|
||||||
|
fn([...allkeys]);
|
||||||
|
allkeys.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
target.addEventListener("keydown", handleKeydown);
|
||||||
|
target.addEventListener("keyup", handleKeyup);
|
||||||
|
return () => {
|
||||||
|
target.removeEventListener("keydown", handleKeydown);
|
||||||
|
target.removeEventListener("keyup", handleKeyup);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册键盘快捷键
|
||||||
|
* @param {*} targetKeys
|
||||||
|
* @param {*} fn
|
||||||
|
* @param {*} target
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const shortcutRegister = (targetKeys, fn, target = document) => {
|
||||||
|
return shortcutListener((keys) => {
|
||||||
|
if (isSameSet(new Set(targetKeys), new Set(keys))) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}, target);
|
||||||
|
};
|
||||||
@@ -6,10 +6,16 @@ import Draggable from "./Draggable";
|
|||||||
import { useEffect, useState, useMemo, useCallback } from "react";
|
import { useEffect, useState, useMemo, useCallback } from "react";
|
||||||
import { SettingProvider } from "../../hooks/Setting";
|
import { SettingProvider } from "../../hooks/Setting";
|
||||||
import Popup from "../Popup";
|
import Popup from "../Popup";
|
||||||
import { debounce, isSameSet } from "../../libs/utils";
|
import { debounce } from "../../libs/utils";
|
||||||
import { isGm } from "../../libs/client";
|
import { isGm } from "../../libs/client";
|
||||||
import Header from "../Popup/Header";
|
import Header from "../Popup/Header";
|
||||||
import { DEFAULT_SHORTCUTS, OPT_SHORTCUT_TRANSLATE } from "../../config";
|
import {
|
||||||
|
DEFAULT_SHORTCUTS,
|
||||||
|
OPT_SHORTCUT_TRANSLATE,
|
||||||
|
OPT_SHORTCUT_STYLE,
|
||||||
|
OPT_SHORTCUT_POPUP,
|
||||||
|
} from "../../config";
|
||||||
|
import { shortcutRegister } from "../../libs/shortcut";
|
||||||
|
|
||||||
export default function Action({ translator, fab }) {
|
export default function Action({ translator, fab }) {
|
||||||
const fabWidth = 40;
|
const fabWidth = 40;
|
||||||
@@ -43,55 +49,27 @@ export default function Action({ translator, fab }) {
|
|||||||
setMoved(true);
|
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(() => {
|
useEffect(() => {
|
||||||
// 注册快捷键
|
// 注册快捷键
|
||||||
const shortcuts = translator.setting.shortcuts || DEFAULT_SHORTCUTS;
|
const shortcuts = translator.setting.shortcuts || DEFAULT_SHORTCUTS;
|
||||||
const keys = new Set();
|
const clearShortcuts = [
|
||||||
|
shortcutRegister(shortcuts[OPT_SHORTCUT_TRANSLATE], () => {
|
||||||
|
translator.toggle();
|
||||||
|
setShowPopup(false);
|
||||||
|
}),
|
||||||
|
shortcutRegister(shortcuts[OPT_SHORTCUT_STYLE], () => {
|
||||||
|
translator.toggleStyle();
|
||||||
|
setShowPopup(false);
|
||||||
|
}),
|
||||||
|
shortcutRegister(shortcuts[OPT_SHORTCUT_POPUP], () => {
|
||||||
|
setShowPopup((pre) => !pre);
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
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 () => {
|
return () => {
|
||||||
window.removeEventListener("keydown", handleKeydown);
|
clearShortcuts.forEach((fn) => {
|
||||||
window.removeEventListener("keyup", handleKeyup);
|
fn();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}, [translator]);
|
}, [translator]);
|
||||||
|
|
||||||
|
|||||||
@@ -27,44 +27,29 @@ import {
|
|||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { useEffect, useState, useRef } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import { useShortcut } from "../../hooks/Shortcut";
|
import { useShortcut } from "../../hooks/Shortcut";
|
||||||
|
import { shortcutListener } from "../../libs/shortcut";
|
||||||
|
|
||||||
function ShortcutItem({ action, label }) {
|
function ShortcutItem({ action, label }) {
|
||||||
const { shortcut, setShortcut } = useShortcut(action);
|
const { shortcut, setShortcut } = useShortcut(action);
|
||||||
const [disabled, setDisabled] = useState(true);
|
const [disabled, setDisabled] = useState(true);
|
||||||
const [focused, setFocus] = useState(false);
|
|
||||||
const [formval, setFormval] = useState(shortcut);
|
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!disabled) {
|
if (disabled) {
|
||||||
inputRef.current.focus();
|
|
||||||
setFormval([]);
|
|
||||||
}
|
|
||||||
}, [disabled]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!focused) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keys = new Set();
|
inputRef.current.focus();
|
||||||
const handleKeydown = (e) => {
|
setShortcut([]);
|
||||||
// console.log("keydown", e);
|
|
||||||
e.code && keys.add(e.key);
|
const clearShortcut = shortcutListener((keys) => {
|
||||||
setFormval([...keys]);
|
setShortcut(keys);
|
||||||
};
|
}, inputRef.current);
|
||||||
const handleKeyup = (e) => {
|
|
||||||
// console.log("keyup", e);
|
|
||||||
keys.delete(e.key);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener("keydown", handleKeydown);
|
|
||||||
window.addEventListener("keyup", handleKeyup);
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("keydown", handleKeydown);
|
clearShortcut();
|
||||||
window.removeEventListener("keyup", handleKeyup);
|
|
||||||
};
|
};
|
||||||
}, [focused]);
|
}, [disabled, setShortcut]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack direction="row">
|
<Stack direction="row">
|
||||||
@@ -72,17 +57,12 @@ function ShortcutItem({ action, label }) {
|
|||||||
size="small"
|
size="small"
|
||||||
label={label}
|
label={label}
|
||||||
name={label}
|
name={label}
|
||||||
value={formval.join(" + ")}
|
value={shortcut.join(" + ")}
|
||||||
fullWidth
|
fullWidth
|
||||||
inputRef={inputRef}
|
inputRef={inputRef}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onFocus={(e) => {
|
onBlur={() => {
|
||||||
setFocus(true);
|
|
||||||
}}
|
|
||||||
onBlur={(e) => {
|
|
||||||
setFocus(false);
|
|
||||||
setDisabled(true);
|
setDisabled(true);
|
||||||
setShortcut(formval);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|||||||
Reference in New Issue
Block a user