feat: tranbox hover trigger
This commit is contained in:
@@ -827,4 +827,20 @@ export const I18N = {
|
|||||||
zh: `获取小牛翻译密钥`,
|
zh: `获取小牛翻译密钥`,
|
||||||
en: `Get NiuTrans APIKey`,
|
en: `Get NiuTrans APIKey`,
|
||||||
},
|
},
|
||||||
|
trigger_mode: {
|
||||||
|
zh: `触发方式`,
|
||||||
|
en: `Trigger Mode`,
|
||||||
|
},
|
||||||
|
trigger_click: {
|
||||||
|
zh: `点击触发`,
|
||||||
|
en: `Click Trigger`,
|
||||||
|
},
|
||||||
|
trigger_hover: {
|
||||||
|
zh: `鼠标悬停触发`,
|
||||||
|
en: `Hover Trigger`,
|
||||||
|
},
|
||||||
|
trigger_select: {
|
||||||
|
zh: `选中触发`,
|
||||||
|
en: `Select Trigger`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -407,6 +407,14 @@ export const DEFAULT_INPUT_RULE = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 划词翻译
|
// 划词翻译
|
||||||
|
export const OPT_TRANBOX_TRIGGER_CLICK = "click";
|
||||||
|
export const OPT_TRANBOX_TRIGGER_HOVER = "hover";
|
||||||
|
export const OPT_TRANBOX_TRIGGER_SELECT = "select";
|
||||||
|
export const OPT_TRANBOX_TRIGGER_ALL = [
|
||||||
|
OPT_TRANBOX_TRIGGER_CLICK,
|
||||||
|
OPT_TRANBOX_TRIGGER_HOVER,
|
||||||
|
OPT_TRANBOX_TRIGGER_SELECT,
|
||||||
|
];
|
||||||
export const DEFAULT_TRANBOX_SHORTCUT = ["AltLeft", "KeyS"];
|
export const DEFAULT_TRANBOX_SHORTCUT = ["AltLeft", "KeyS"];
|
||||||
export const DEFAULT_TRANBOX_SETTING = {
|
export const DEFAULT_TRANBOX_SETTING = {
|
||||||
transOpen: true,
|
transOpen: true,
|
||||||
@@ -418,8 +426,9 @@ export const DEFAULT_TRANBOX_SETTING = {
|
|||||||
btnOffsetX: 10,
|
btnOffsetX: 10,
|
||||||
btnOffsetY: 10,
|
btnOffsetY: 10,
|
||||||
hideTranBtn: false, // 是否隐藏翻译按钮
|
hideTranBtn: false, // 是否隐藏翻译按钮
|
||||||
hideClickAway: false, // 默认是否点击外部关闭弹窗
|
hideClickAway: false, // 是否点击外部关闭弹窗
|
||||||
simpleStyle: false, // 默认是否简洁界面
|
simpleStyle: false, // 是否简洁界面
|
||||||
|
triggerMode: OPT_TRANBOX_TRIGGER_CLICK, // 触发翻译方式
|
||||||
};
|
};
|
||||||
|
|
||||||
// 订阅列表
|
// 订阅列表
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
|
|||||||
fullWidth
|
fullWidth
|
||||||
name="transTiming"
|
name="transTiming"
|
||||||
value={transTiming}
|
value={transTiming}
|
||||||
label={i18n("translate_timing")}
|
label={i18n("trigger_mode")}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,7 +3,13 @@ import Stack from "@mui/material/Stack";
|
|||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import { useI18n } from "../../hooks/I18n";
|
import { useI18n } from "../../hooks/I18n";
|
||||||
import { OPT_TRANS_ALL, OPT_LANGS_FROM, OPT_LANGS_TO } from "../../config";
|
import {
|
||||||
|
OPT_TRANS_ALL,
|
||||||
|
OPT_LANGS_FROM,
|
||||||
|
OPT_LANGS_TO,
|
||||||
|
OPT_TRANBOX_TRIGGER_CLICK,
|
||||||
|
OPT_TRANBOX_TRIGGER_ALL,
|
||||||
|
} from "../../config";
|
||||||
import ShortcutInput from "./ShortcutInput";
|
import ShortcutInput from "./ShortcutInput";
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
import Switch from "@mui/material/Switch";
|
import Switch from "@mui/material/Switch";
|
||||||
@@ -52,6 +58,7 @@ export default function Tranbox() {
|
|||||||
hideTranBtn = false,
|
hideTranBtn = false,
|
||||||
hideClickAway = false,
|
hideClickAway = false,
|
||||||
simpleStyle = false,
|
simpleStyle = false,
|
||||||
|
triggerMode = OPT_TRANBOX_TRIGGER_CLICK,
|
||||||
} = tranboxSetting;
|
} = tranboxSetting;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -186,6 +193,21 @@ export default function Tranbox() {
|
|||||||
<MenuItem value={true}>{i18n("enable")}</MenuItem>
|
<MenuItem value={true}>{i18n("enable")}</MenuItem>
|
||||||
</TextField>
|
</TextField>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
select
|
||||||
|
size="small"
|
||||||
|
name="triggerMode"
|
||||||
|
value={triggerMode}
|
||||||
|
label={i18n("trigger_mode")}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
{OPT_TRANBOX_TRIGGER_ALL.map((item) => (
|
||||||
|
<MenuItem key={item} value={item}>
|
||||||
|
{i18n(`trigger_${item}`)}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
|
||||||
{!isExt && (
|
{!isExt && (
|
||||||
<ShortcutInput
|
<ShortcutInput
|
||||||
value={tranboxShortcut}
|
value={tranboxShortcut}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { isMobile } from "../../libs/mobile";
|
import { isMobile } from "../../libs/mobile";
|
||||||
import { limitNumber } from "../../libs/utils";
|
import { limitNumber } from "../../libs/utils";
|
||||||
|
|
||||||
export default function TranBtn({ onClick, position, tranboxSetting }) {
|
export default function TranBtn({
|
||||||
|
onTrigger,
|
||||||
|
btnEvent,
|
||||||
|
position,
|
||||||
|
tranboxSetting,
|
||||||
|
}) {
|
||||||
const left = limitNumber(
|
const left = limitNumber(
|
||||||
position.x + tranboxSetting.btnOffsetX,
|
position.x + tranboxSetting.btnOffsetX,
|
||||||
0,
|
0,
|
||||||
@@ -13,14 +18,6 @@ export default function TranBtn({ onClick, position, tranboxSetting }) {
|
|||||||
window.innerHeight - 32
|
window.innerHeight - 32
|
||||||
);
|
);
|
||||||
|
|
||||||
const touchProps = isMobile
|
|
||||||
? {
|
|
||||||
onTouchEnd: onClick,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
onMouseUp: onClick,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -31,7 +28,7 @@ export default function TranBtn({ onClick, position, tranboxSetting }) {
|
|||||||
top,
|
top,
|
||||||
zIndex: 2147483647,
|
zIndex: 2147483647,
|
||||||
}}
|
}}
|
||||||
{...touchProps}
|
{...{ [btnEvent]: onTrigger }}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback, useMemo } from "react";
|
||||||
import TranBtn from "./TranBtn";
|
import TranBtn from "./TranBtn";
|
||||||
import TranBox from "./TranBox";
|
import TranBox from "./TranBox";
|
||||||
import { shortcutRegister } from "../../libs/shortcut";
|
import { shortcutRegister } from "../../libs/shortcut";
|
||||||
import { sleep, limitNumber } from "../../libs/utils";
|
import { sleep, limitNumber } from "../../libs/utils";
|
||||||
import { isGm, isExt } from "../../libs/client";
|
import { isGm, isExt } from "../../libs/client";
|
||||||
import { MSG_OPEN_TRANBOX, DEFAULT_TRANBOX_SHORTCUT } from "../../config";
|
import {
|
||||||
|
MSG_OPEN_TRANBOX,
|
||||||
|
DEFAULT_TRANBOX_SHORTCUT,
|
||||||
|
OPT_TRANBOX_TRIGGER_CLICK,
|
||||||
|
OPT_TRANBOX_TRIGGER_HOVER,
|
||||||
|
OPT_TRANBOX_TRIGGER_SELECT,
|
||||||
|
} from "../../config";
|
||||||
import { isMobile } from "../../libs/mobile";
|
import { isMobile } from "../../libs/mobile";
|
||||||
import { kissLog } from "../../libs/log";
|
import { kissLog } from "../../libs/log";
|
||||||
|
|
||||||
@@ -13,12 +19,20 @@ export default function Slection({
|
|||||||
tranboxSetting,
|
tranboxSetting,
|
||||||
transApis,
|
transApis,
|
||||||
}) {
|
}) {
|
||||||
|
const {
|
||||||
|
hideTranBtn = false,
|
||||||
|
simpleStyle: initSimpleStyle = false,
|
||||||
|
hideClickAway: initHideClickAway = false,
|
||||||
|
tranboxShortcut = DEFAULT_TRANBOX_SHORTCUT,
|
||||||
|
triggerMode = OPT_TRANBOX_TRIGGER_CLICK,
|
||||||
|
} = tranboxSetting;
|
||||||
|
|
||||||
const boxWidth =
|
const boxWidth =
|
||||||
isMobile || tranboxSetting.simpleStyle
|
isMobile || initSimpleStyle
|
||||||
? 300
|
? 300
|
||||||
: limitNumber(window.innerWidth, 300, 600);
|
: limitNumber(window.innerWidth, 300, 600);
|
||||||
const boxHeight =
|
const boxHeight =
|
||||||
isMobile || tranboxSetting.simpleStyle
|
isMobile || initSimpleStyle
|
||||||
? 200
|
? 200
|
||||||
: limitNumber(window.innerHeight, 200, 400);
|
: limitNumber(window.innerHeight, 200, 400);
|
||||||
|
|
||||||
@@ -35,18 +49,17 @@ export default function Slection({
|
|||||||
x: (window.innerWidth - boxWidth) / 2,
|
x: (window.innerWidth - boxWidth) / 2,
|
||||||
y: (window.innerHeight - boxHeight) / 2,
|
y: (window.innerHeight - boxHeight) / 2,
|
||||||
});
|
});
|
||||||
const [simpleStyle, setSimpleStyle] = useState(!!tranboxSetting.simpleStyle);
|
const [simpleStyle, setSimpleStyle] = useState(initSimpleStyle);
|
||||||
const [hideClickAway, setHideClickAway] = useState(
|
const [hideClickAway, setHideClickAway] = useState(initHideClickAway);
|
||||||
!!tranboxSetting.hideClickAway
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
|
const handleTrigger = useCallback(
|
||||||
|
(text) => {
|
||||||
setShowBtn(false);
|
setShowBtn(false);
|
||||||
setText(selectedText);
|
setText(text || selectedText);
|
||||||
setShowBox(true);
|
setShowBox(true);
|
||||||
};
|
},
|
||||||
|
[selectedText]
|
||||||
|
);
|
||||||
|
|
||||||
const handleTranbox = useCallback(() => {
|
const handleTranbox = useCallback(() => {
|
||||||
setShowBtn(false);
|
setShowBtn(false);
|
||||||
@@ -62,10 +75,19 @@ export default function Slection({
|
|||||||
setShowBox(true);
|
setShowBox(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const btnEvent = useMemo(() => {
|
||||||
|
if (isMobile) {
|
||||||
|
return "onTouchEnd";
|
||||||
|
} else if (triggerMode === OPT_TRANBOX_TRIGGER_HOVER) {
|
||||||
|
return "onMouseOver";
|
||||||
|
}
|
||||||
|
return "onMouseUp";
|
||||||
|
}, [triggerMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function handleMouseup(e) {
|
async function handleMouseup(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
await sleep(100);
|
await sleep(200);
|
||||||
|
|
||||||
const selectedText = window.getSelection()?.toString()?.trim() || "";
|
const selectedText = window.getSelection()?.toString()?.trim() || "";
|
||||||
setSelText(selectedText);
|
setSelText(selectedText);
|
||||||
@@ -74,8 +96,13 @@ export default function Slection({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (triggerMode === OPT_TRANBOX_TRIGGER_SELECT) {
|
||||||
|
handleTrigger(selectedText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { clientX, clientY } = isMobile ? e.changedTouches[0] : e;
|
const { clientX, clientY } = isMobile ? e.changedTouches[0] : e;
|
||||||
!tranboxSetting.hideTranBtn && setShowBtn(true);
|
setShowBtn(!hideTranBtn);
|
||||||
// setPosition({ x: e.clientX, y: e.clientY });
|
// setPosition({ x: e.clientX, y: e.clientY });
|
||||||
setPosition({ x: clientX, y: clientY });
|
setPosition({ x: clientX, y: clientY });
|
||||||
}
|
}
|
||||||
@@ -89,22 +116,17 @@ export default function Slection({
|
|||||||
handleMouseup
|
handleMouseup
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}, [tranboxSetting.hideTranBtn]);
|
}, [hideTranBtn, triggerMode, handleTrigger]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isExt) {
|
if (isExt) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const clearShortcut = shortcutRegister(tranboxShortcut, handleTranbox);
|
||||||
const clearShortcut = shortcutRegister(
|
|
||||||
tranboxSetting.tranboxShortcut || DEFAULT_TRANBOX_SHORTCUT,
|
|
||||||
handleTranbox
|
|
||||||
);
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearShortcut();
|
clearShortcut();
|
||||||
};
|
};
|
||||||
}, [tranboxSetting.tranboxShortcut, handleTranbox]);
|
}, [tranboxShortcut, handleTranbox]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener(MSG_OPEN_TRANBOX, handleTranbox);
|
window.addEventListener(MSG_OPEN_TRANBOX, handleTranbox);
|
||||||
@@ -178,7 +200,11 @@ export default function Slection({
|
|||||||
<TranBtn
|
<TranBtn
|
||||||
position={position}
|
position={position}
|
||||||
tranboxSetting={tranboxSetting}
|
tranboxSetting={tranboxSetting}
|
||||||
onClick={handleClick}
|
btnEvent={btnEvent}
|
||||||
|
onTrigger={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleTrigger();
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user