diff --git a/src/config/i18n.js b/src/config/i18n.js
index c674564..ab4b11e 100644
--- a/src/config/i18n.js
+++ b/src/config/i18n.js
@@ -547,4 +547,28 @@ export const I18N = {
zh: `全局规则`,
en: `Global Rule`,
},
+ input_setting: {
+ zh: `输入框设置`,
+ en: `Input Box Setting`,
+ },
+ input_box_translation: {
+ zh: `启用输入框翻译`,
+ en: `Input Box Translation`,
+ },
+ input_selector: {
+ zh: `输入框选择器`,
+ en: `Input Selector`,
+ },
+ input_selector_helper: {
+ zh: `用于输入框翻译。`,
+ en: `Used for input box translation.`,
+ },
+ trigger_trans_shortcut: {
+ zh: `触发翻译快捷键`,
+ en: `Trigger Translation Shortcut Keys`,
+ },
+ trigger_trans_count: {
+ zh: `触发翻译连击次数`,
+ en: `Trigger Translation Press Nunber`,
+ },
};
diff --git a/src/config/index.js b/src/config/index.js
index 3d4b2fa..702ef8d 100644
--- a/src/config/index.js
+++ b/src/config/index.js
@@ -189,6 +189,7 @@ export const DEFAULT_COLOR = "#209CEE"; // 默认高亮背景色/线条颜色
export const GLOBLA_RULE = {
pattern: "*",
selector: DEFAULT_SELECTOR,
+ inputSelector: "",
translator: OPT_TRANS_MICROSOFT,
fromLang: "auto",
toLang: "zh-CN",
@@ -198,6 +199,15 @@ export const GLOBLA_RULE = {
textDiyStyle: "",
};
+export const DEFAULT_INPUT_RULE = {
+ transOpen: true,
+ translator: OPT_TRANS_MICROSOFT,
+ fromLang: "auto",
+ toLang: "en",
+ triggerShortcut: ["Alt", "i"],
+ triggerCount: 1,
+};
+
// 订阅列表
export const DEFAULT_SUBRULES_LIST = [
{
@@ -273,6 +283,7 @@ export const DEFAULT_SETTING = {
mouseKey: OPT_MOUSEKEY_DISABLE, // 鼠标悬停翻译
shortcuts: DEFAULT_SHORTCUTS, // 快捷键
hideFab: false, // 是否隐藏按钮
+ inputRule: DEFAULT_INPUT_RULE, // 输入框设置
};
export const DEFAULT_RULES = [GLOBLA_RULE];
diff --git a/src/config/rules.js b/src/config/rules.js
index 4e65439..d15fdb8 100644
--- a/src/config/rules.js
+++ b/src/config/rules.js
@@ -10,6 +10,7 @@ export const SHADOW_KEY = ">>>";
export const DEFAULT_RULE = {
pattern: "",
selector: "",
+ inputSelector: "",
translator: GLOBAL_KEY,
fromLang: GLOBAL_KEY,
toLang: GLOBAL_KEY,
diff --git a/src/hooks/InputRule.js b/src/hooks/InputRule.js
new file mode 100644
index 0000000..6d14450
--- /dev/null
+++ b/src/hooks/InputRule.js
@@ -0,0 +1,18 @@
+import { useCallback } from "react";
+import { DEFAULT_INPUT_RULE } from "../config";
+import { useSetting } from "./Setting";
+
+export function useInputRule() {
+ const { setting, updateSetting } = useSetting();
+ const inputRule = setting?.inputRule || DEFAULT_INPUT_RULE;
+
+ const updateInputRule = useCallback(
+ async (obj) => {
+ Object.assign(inputRule, obj);
+ await updateSetting({ inputRule });
+ },
+ [inputRule, updateSetting]
+ );
+
+ return { inputRule, updateInputRule };
+}
diff --git a/src/libs/shortcut.js b/src/libs/shortcut.js
index c0803f3..c29f98f 100644
--- a/src/libs/shortcut.js
+++ b/src/libs/shortcut.js
@@ -65,3 +65,41 @@ export const shortcutRegister = (targetKeys = [], fn, target = document) => {
}
}, target);
};
+
+/**
+ * 注册连续快捷键
+ * @param {*} targetKeys
+ * @param {*} fn
+ * @param {*} step
+ * @param {*} timeout
+ * @param {*} target
+ * @returns
+ */
+export const stepShortcutRegister = (
+ targetKeys = [],
+ fn,
+ step = 3,
+ timeout = 500,
+ target = document
+) => {
+ let count = 0;
+ let pre = Date.now();
+ return shortcutListener((curkeys) => {
+ if (targetKeys.length > 0) {
+ const now = Date.now();
+ if (
+ (count === 0 || now - pre < timeout) &&
+ isSameSet(new Set(targetKeys), new Set(curkeys))
+ ) {
+ count++;
+ if (count === step) {
+ count = 0;
+ fn();
+ }
+ } else {
+ count = 0;
+ }
+ pre = now;
+ }
+ }, target);
+};
diff --git a/src/views/Options/InputSetting.js b/src/views/Options/InputSetting.js
new file mode 100644
index 0000000..ca686a8
--- /dev/null
+++ b/src/views/Options/InputSetting.js
@@ -0,0 +1,134 @@
+import Box from "@mui/material/Box";
+import Stack from "@mui/material/Stack";
+import TextField from "@mui/material/TextField";
+import MenuItem from "@mui/material/MenuItem";
+import { limitNumber } from "../../libs/utils";
+import { useI18n } from "../../hooks/I18n";
+import { OPT_TRANS_ALL, OPT_LANGS_FROM, OPT_LANGS_TO } from "../../config";
+import ShortcutInput from "./ShortcutInput";
+import FormControlLabel from "@mui/material/FormControlLabel";
+import Switch from "@mui/material/Switch";
+import { useInputRule } from "../../hooks/InputRule";
+import { useCallback } from "react";
+
+export default function InputSetting() {
+ const i18n = useI18n();
+ const { inputRule, updateInputRule } = useInputRule();
+
+ const handleChange = (e) => {
+ e.preventDefault();
+ let { name, value } = e.target;
+ console.log({ name, value });
+ switch (name) {
+ case "triggerCount":
+ value = limitNumber(value, 1, 3);
+ break;
+ default:
+ }
+ updateInputRule({
+ [name]: value,
+ });
+ };
+
+ const handleShortcutInput = useCallback(
+ (val) => {
+ updateInputRule({ triggerShortcut: val });
+ },
+ [updateInputRule]
+ );
+
+ const {
+ transOpen,
+ translator,
+ fromLang,
+ toLang,
+ triggerShortcut,
+ triggerCount,
+ } = inputRule;
+
+ return (
+
+
+ {
+ updateInputRule({ transOpen: !transOpen });
+ }}
+ />
+ }
+ label={i18n("input_box_translation")}
+ />
+
+
+ {OPT_TRANS_ALL.map((item) => (
+
+ ))}
+
+
+
+ {OPT_LANGS_FROM.map(([lang, name]) => (
+
+ ))}
+
+
+
+ {OPT_LANGS_TO.map(([lang, name]) => (
+
+ ))}
+
+
+
+
+
+ {[1, 2, 3].map((val) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/views/Options/Navigator.js b/src/views/Options/Navigator.js
index 133b533..06d4125 100644
--- a/src/views/Options/Navigator.js
+++ b/src/views/Options/Navigator.js
@@ -12,6 +12,7 @@ import { useI18n } from "../../hooks/I18n";
import SyncIcon from "@mui/icons-material/Sync";
import ApiIcon from "@mui/icons-material/Api";
import SendTimeExtensionIcon from "@mui/icons-material/SendTimeExtension";
+import InputIcon from "@mui/icons-material/Input";
function LinkItem({ label, url, icon }) {
const match = useMatch(url);
@@ -38,6 +39,12 @@ export default function Navigator(props) {
url: "/rules",
icon: ,
},
+ {
+ id: "input_setting",
+ label: i18n("input_setting"),
+ url: "/input",
+ icon: ,
+ },
{
id: "apis_setting",
label: i18n("apis_setting"),
diff --git a/src/views/Options/Rules.js b/src/views/Options/Rules.js
index d53de57..02db939 100644
--- a/src/views/Options/Rules.js
+++ b/src/views/Options/Rules.js
@@ -64,6 +64,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
const {
pattern,
selector,
+ inputSelector = "",
translator,
fromLang,
toLang,
@@ -178,6 +179,17 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
onFocus={handleFocus}
multiline
/>
+
diff --git a/src/views/Options/Setting.js b/src/views/Options/Setting.js
index cf35b04..f41978a 100644
--- a/src/views/Options/Setting.js
+++ b/src/views/Options/Setting.js
@@ -12,8 +12,6 @@ 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,
@@ -26,57 +24,13 @@ import {
OPT_SHORTCUT_POPUP,
OPT_SHORTCUT_SETTING,
} from "../../config";
-import { useEffect, useState, useRef } from "react";
import { useShortcut } from "../../hooks/Shortcut";
-import { shortcutListener } from "../../libs/shortcut";
+import ShortcutInput from "./ShortcutInput";
function ShortcutItem({ action, label }) {
const { shortcut, setShortcut } = useShortcut(action);
- const [disabled, setDisabled] = useState(true);
- const inputRef = useRef(null);
-
- useEffect(() => {
- if (disabled) {
- return;
- }
-
- inputRef.current.focus();
- setShortcut([]);
-
- const clearShortcut = shortcutListener((curkeys, allkeys) => {
- setShortcut(allkeys);
- if (curkeys.length === 0) {
- setDisabled(true);
- }
- }, inputRef.current);
-
- return () => {
- clearShortcut();
- };
- }, [disabled, setShortcut]);
-
return (
-
- {
- setDisabled(true);
- }}
- />
- {
- setDisabled(false);
- }}
- >
- {}
-
-
+
);
}
diff --git a/src/views/Options/ShortcutInput.js b/src/views/Options/ShortcutInput.js
new file mode 100644
index 0000000..77cb4ae
--- /dev/null
+++ b/src/views/Options/ShortcutInput.js
@@ -0,0 +1,55 @@
+import Stack from "@mui/material/Stack";
+import TextField from "@mui/material/TextField";
+import IconButton from "@mui/material/IconButton";
+import EditIcon from "@mui/icons-material/Edit";
+import { useEffect, useState, useRef } from "react";
+import { shortcutListener } from "../../libs/shortcut";
+
+export default function ShortcutInput({ value, onChange, label }) {
+ const [disabled, setDisabled] = useState(true);
+ const inputRef = useRef(null);
+
+ useEffect(() => {
+ if (disabled) {
+ return;
+ }
+
+ inputRef.current.focus();
+ onChange([]);
+
+ const clearShortcut = shortcutListener((curkeys, allkeys) => {
+ onChange(allkeys);
+ if (curkeys.length === 0) {
+ setDisabled(true);
+ }
+ }, inputRef.current);
+
+ return () => {
+ clearShortcut();
+ };
+ }, [disabled, onChange]);
+
+ return (
+
+ (item === " " ? "Space" : item)).join(" + ")}
+ fullWidth
+ inputRef={inputRef}
+ disabled={disabled}
+ onBlur={() => {
+ setDisabled(true);
+ }}
+ />
+ {
+ setDisabled(false);
+ }}
+ >
+ {}
+
+
+ );
+}
diff --git a/src/views/Options/index.js b/src/views/Options/index.js
index ec8d5e6..9951293 100644
--- a/src/views/Options/index.js
+++ b/src/views/Options/index.js
@@ -19,6 +19,7 @@ import { adaptScript } from "../../libs/gm";
import Alert from "@mui/material/Alert";
import Apis from "./Apis";
import Webfix from "./Webfix";
+import InputSetting from "./InputSetting";
export default function Options() {
const [error, setError] = useState("");
@@ -82,16 +83,20 @@ export default function Options() {
- Install Userscript for Tampermonkey/Violentmonkey 1 (油猴脚本 安装地址 1)
+ Install Userscript for Tampermonkey/Violentmonkey 1 (油猴脚本
+ 安装地址 1)
- Install Userscript for Tampermonkey/Violentmonkey 2 (油猴脚本 安装地址 2)
+ Install Userscript for Tampermonkey/Violentmonkey 2 (油猴脚本
+ 安装地址 2)
- Install Userscript for iOS Safari 1 (油猴脚本 iOS Safari专用 安装地址 1)
+ Install Userscript for iOS Safari 1 (油猴脚本 iOS Safari专用
+ 安装地址 1)
- Install Userscript for iOS Safari 2 (油猴脚本 iOS Safari专用 安装地址 2)
+ Install Userscript for iOS Safari 2 (油猴脚本 iOS Safari专用
+ 安装地址 2)
Open Options Page 1 (打开设置页面 1)
@@ -126,6 +131,7 @@ export default function Options() {
}>
} />
} />
+ } />
} />
} />
} />