diff --git a/src/config/i18n.js b/src/config/i18n.js
index 3854818..a29fb80 100644
--- a/src/config/i18n.js
+++ b/src/config/i18n.js
@@ -643,4 +643,20 @@ export const I18N = {
zh: `收藏词汇`,
en: `Favorite Words`,
},
+ touch_setting: {
+ zh: `触屏设置`,
+ en: `Touch Setting`,
+ },
+ touch_tap_0: {
+ zh: `禁用`,
+ en: `Disable`,
+ },
+ touch_tap_2: {
+ zh: `双指轻触`,
+ en: `Two finger tap`,
+ },
+ touch_tap_3: {
+ zh: `三指轻触`,
+ en: `Three finger tap`,
+ },
};
diff --git a/src/config/index.js b/src/config/index.js
index 753983d..6d281ed 100644
--- a/src/config/index.js
+++ b/src/config/index.js
@@ -404,6 +404,14 @@ export const TRANS_MIN_LENGTH = 5; // 最短翻译长度
export const TRANS_MAX_LENGTH = 5000; // 最长翻译长度
export const TRANS_NEWLINE_LENGTH = 20; // 换行字符数
+// 触屏操作
+export const DEFAULT_TOUCH_OPERATION = {
+ [OPT_SHORTCUT_TRANSLATE]: [2, 1, 500],
+ [OPT_SHORTCUT_STYLE]: [3, 1, 500],
+ [OPT_SHORTCUT_POPUP]: [0, 1, 500],
+ [OPT_SHORTCUT_SETTING]: [3, 2, 500],
+};
+
export const DEFAULT_SETTING = {
darkMode: false, // 深色模式
uiLang: "en", // 界面语言
@@ -423,6 +431,7 @@ export const DEFAULT_SETTING = {
shortcuts: DEFAULT_SHORTCUTS, // 快捷键
inputRule: DEFAULT_INPUT_RULE, // 输入框设置
tranboxSetting: DEFAULT_TRANBOX_SETTING, // 划词翻译设置
+ touchOperations: DEFAULT_TOUCH_OPERATION, // 触屏操作
};
export const DEFAULT_RULES = [GLOBLA_RULE];
diff --git a/src/hooks/Touch.js b/src/hooks/Touch.js
new file mode 100644
index 0000000..ca462d2
--- /dev/null
+++ b/src/hooks/Touch.js
@@ -0,0 +1,19 @@
+import { useCallback } from "react";
+import { DEFAULT_TOUCH_OPERATION } from "../config";
+import { useSetting } from "./Setting";
+
+export function useTouch(action) {
+ const { setting, updateSetting } = useSetting();
+ const touchOperations = setting?.touchOperations || DEFAULT_TOUCH_OPERATION;
+ const touchOperation = touchOperations[action];
+
+ const setTouchOperation = useCallback(
+ async (val, idx) => {
+ touchOperations[action][idx] = val;
+ await updateSetting({ touchOperations: { ...touchOperations } });
+ },
+ [action, touchOperations, updateSetting]
+ );
+
+ return { touchOperation, setTouchOperation };
+}
diff --git a/src/libs/touch.js b/src/libs/touch.js
new file mode 100644
index 0000000..942e8e8
--- /dev/null
+++ b/src/libs/touch.js
@@ -0,0 +1,31 @@
+export function touchTapListener(fn, setting) {
+ const [touchLength, touchCount, touchTime] = setting;
+
+ let lastTouch = 0;
+ let curCount = 0;
+ const handleTouchend = (e) => {
+ if (e.touches.length !== touchLength) {
+ return;
+ }
+
+ const timer = setTimeout(() => {
+ clearTimeout(timer);
+ curCount = 0;
+ }, touchTime);
+
+ curCount++;
+ const now = Date.now();
+ if (curCount === touchCount && now - lastTouch <= touchTime) {
+ timer && clearTimeout(timer);
+ curCount = 0;
+ fn();
+ }
+
+ lastTouch = now;
+ };
+
+ document.addEventListener("touchend", handleTouchend);
+ return () => {
+ document.removeEventListener("touchend", handleTouchend);
+ };
+}
diff --git a/src/views/Options/Navigator.js b/src/views/Options/Navigator.js
index bd00c1e..c796d8b 100644
--- a/src/views/Options/Navigator.js
+++ b/src/views/Options/Navigator.js
@@ -13,8 +13,9 @@ 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";
-import SelectAllIcon from '@mui/icons-material/SelectAll';
-import EventNoteIcon from '@mui/icons-material/EventNote';
+import SelectAllIcon from "@mui/icons-material/SelectAll";
+import EventNoteIcon from "@mui/icons-material/EventNote";
+import TouchAppIcon from "@mui/icons-material/TouchApp";
function LinkItem({ label, url, icon }) {
const match = useMatch(url);
@@ -47,6 +48,12 @@ export default function Navigator(props) {
url: "/input",
icon: ,
},
+ {
+ id: "touch_setting",
+ label: i18n("touch_setting"),
+ url: "/touch",
+ icon: ,
+ },
{
id: "selection_translate",
label: i18n("selection_translate"),
diff --git a/src/views/Options/index.js b/src/views/Options/index.js
index 6170369..56f0bcb 100644
--- a/src/views/Options/index.js
+++ b/src/views/Options/index.js
@@ -22,6 +22,7 @@ import Webfix from "./Webfix";
import InputSetting from "./InputSetting";
import Tranbox from "./Tranbox";
import FavWords from "./FavWords";
+import TouchSetting from "./touchSetting";
export default function Options() {
const [error, setError] = useState("");
@@ -122,6 +123,7 @@ export default function Options() {
} />
} />
} />
+ } />
} />
} />
} />
diff --git a/src/views/Options/touchSetting.js b/src/views/Options/touchSetting.js
new file mode 100644
index 0000000..22adbb6
--- /dev/null
+++ b/src/views/Options/touchSetting.js
@@ -0,0 +1,103 @@
+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 { useI18n } from "../../hooks/I18n";
+import {
+ OPT_SHORTCUT_TRANSLATE,
+ OPT_SHORTCUT_STYLE,
+ OPT_SHORTCUT_POPUP,
+ OPT_SHORTCUT_SETTING,
+} from "../../config";
+import Grid from "@mui/material/Grid";
+import { limitNumber } from "../../libs/utils";
+import { useTouch } from "../../hooks/Touch";
+
+function TouchItem({ action, name }) {
+ const i18n = useI18n();
+ const { touchOperation, setTouchOperation } = useTouch(action);
+ const [triggerShortcut, triggerCount, triggerTime] = touchOperation;
+
+ const handleChangeShortcut = (e) => {
+ const value = limitNumber(e.target.value, 0, 3);
+ setTouchOperation(value, 0);
+ };
+
+ const handleChangeCount = (e) => {
+ const value = limitNumber(e.target.value, 1, 3);
+ setTouchOperation(value, 2);
+ };
+
+ const handleChangeTime = (e) => {
+ const value = limitNumber(e.target.value, 100, 1000);
+ setTouchOperation(value, 3);
+ };
+
+ return (
+
+
+
+
+ {[0, 2, 3].map((val) => (
+
+ ))}
+
+
+
+
+ {[1, 2, 3].map((val) => (
+
+ ))}
+
+
+
+
+
+
+
+ );
+}
+
+export default function TouchSetting() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}