feat: more touch operations
This commit is contained in:
@@ -1184,6 +1184,21 @@ export const I18N = {
|
|||||||
en: `Four finger tap`,
|
en: `Four finger tap`,
|
||||||
zh_TW: `四指輕觸`,
|
zh_TW: `四指輕觸`,
|
||||||
},
|
},
|
||||||
|
touch_tap_5: {
|
||||||
|
zh: `单指双击`,
|
||||||
|
en: `Double-click`,
|
||||||
|
zh_TW: `單指雙擊`,
|
||||||
|
},
|
||||||
|
touch_tap_6: {
|
||||||
|
zh: `单指三击`,
|
||||||
|
en: `Triple-click`,
|
||||||
|
zh_TW: `單指三擊`,
|
||||||
|
},
|
||||||
|
touch_tap_7: {
|
||||||
|
zh: `双指双击`,
|
||||||
|
en: `Two-finger double-click`,
|
||||||
|
zh_TW: `雙指雙擊`,
|
||||||
|
},
|
||||||
translate_blacklist: {
|
translate_blacklist: {
|
||||||
zh: `禁用翻译名单`,
|
zh: `禁用翻译名单`,
|
||||||
en: `Translate Blacklist`,
|
en: `Translate Blacklist`,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export const MSG_TRANS_GETRULE = "trans_getrule";
|
|||||||
export const MSG_TRANS_PUTRULE = "trans_putrule";
|
export const MSG_TRANS_PUTRULE = "trans_putrule";
|
||||||
export const MSG_TRANS_CURRULE = "trans_currule";
|
export const MSG_TRANS_CURRULE = "trans_currule";
|
||||||
export const MSG_TRANSBOX_TOGGLE = "transbox_toggle";
|
export const MSG_TRANSBOX_TOGGLE = "transbox_toggle";
|
||||||
|
export const MSG_POPUP_TOGGLE = "popup_toggle";
|
||||||
export const MSG_MOUSEHOVER_TOGGLE = "mousehover_toggle";
|
export const MSG_MOUSEHOVER_TOGGLE = "mousehover_toggle";
|
||||||
export const MSG_TRANSINPUT_TOGGLE = "transinput_toggle";
|
export const MSG_TRANSINPUT_TOGGLE = "transinput_toggle";
|
||||||
export const MSG_CONTEXT_MENUS = "context_menus";
|
export const MSG_CONTEXT_MENUS = "context_menus";
|
||||||
@@ -27,6 +28,8 @@ export const MSG_BUILTINAI_TRANSLATE = "builtinai_translte";
|
|||||||
export const MSG_SET_LOGLEVEL = "set_loglevel";
|
export const MSG_SET_LOGLEVEL = "set_loglevel";
|
||||||
export const MSG_CLEAR_CACHES = "clear_caches";
|
export const MSG_CLEAR_CACHES = "clear_caches";
|
||||||
|
|
||||||
|
export const EVENT_KISS = "event_kiss_translate";
|
||||||
|
|
||||||
export const MSG_XHR_DATA_YOUTUBE = "KISS_XHR_DATA_YOUTUBE";
|
export const MSG_XHR_DATA_YOUTUBE = "KISS_XHR_DATA_YOUTUBE";
|
||||||
// export const MSG_GLOBAL_VAR_FETCH = "KISS_GLOBAL_VAR_FETCH";
|
// export const MSG_GLOBAL_VAR_FETCH = "KISS_GLOBAL_VAR_FETCH";
|
||||||
// export const MSG_GLOBAL_VAR_BACK = "KISS_GLOBAL_VAR_BACK";
|
// export const MSG_GLOBAL_VAR_BACK = "KISS_GLOBAL_VAR_BACK";
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ export const DEFAULT_SETTING = {
|
|||||||
shortcuts: DEFAULT_SHORTCUTS, // 快捷键
|
shortcuts: DEFAULT_SHORTCUTS, // 快捷键
|
||||||
inputRule: DEFAULT_INPUT_RULE, // 输入框设置
|
inputRule: DEFAULT_INPUT_RULE, // 输入框设置
|
||||||
tranboxSetting: DEFAULT_TRANBOX_SETTING, // 划词翻译设置
|
tranboxSetting: DEFAULT_TRANBOX_SETTING, // 划词翻译设置
|
||||||
touchTranslate: 2, // 触屏翻译
|
touchTranslate: 2, // 触屏翻译 {5:单指双击,6:单指三击,7:双指双击}
|
||||||
blacklist: DEFAULT_BLACKLIST.join(",\n"), // 禁用翻译名单
|
blacklist: DEFAULT_BLACKLIST.join(",\n"), // 禁用翻译名单
|
||||||
csplist: DEFAULT_CSPLIST.join(",\n"), // 禁用CSP名单
|
csplist: DEFAULT_CSPLIST.join(",\n"), // 禁用CSP名单
|
||||||
orilist: DEFAULT_ORILIST.join(",\n"), // 禁用CSP名单
|
orilist: DEFAULT_ORILIST.join(",\n"), // 禁用CSP名单
|
||||||
|
|||||||
@@ -3,12 +3,16 @@ import { APP_CONSTS } from "../config";
|
|||||||
import ContentFab from "../views/Action/ContentFab";
|
import ContentFab from "../views/Action/ContentFab";
|
||||||
|
|
||||||
export class FabManager extends ShadowDomManager {
|
export class FabManager extends ShadowDomManager {
|
||||||
constructor({ translator, popupManager, fabConfig }) {
|
constructor({ translator, processActions, fabConfig }) {
|
||||||
super({
|
super({
|
||||||
id: APP_CONSTS.fabID,
|
id: APP_CONSTS.fabID,
|
||||||
className: "notranslate",
|
className: "notranslate",
|
||||||
reactComponent: ContentFab,
|
reactComponent: ContentFab,
|
||||||
props: { translator, popupManager, fabConfig },
|
props: { translator, processActions, fabConfig },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!fabConfig?.isHide) {
|
||||||
|
this.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
import ShadowDomManager from "./shadowDomManager";
|
import ShadowDomManager from "./shadowDomManager";
|
||||||
import { APP_CONSTS } from "../config";
|
import { APP_CONSTS, EVENT_KISS, MSG_POPUP_TOGGLE } from "../config";
|
||||||
import Action from "../views/Action";
|
import Action from "../views/Action";
|
||||||
|
|
||||||
export class PopupManager extends ShadowDomManager {
|
export class PopupManager extends ShadowDomManager {
|
||||||
constructor({ translator }) {
|
constructor({ translator, processActions }) {
|
||||||
super({
|
super({
|
||||||
id: APP_CONSTS.popupID,
|
id: APP_CONSTS.popupID,
|
||||||
className: "notranslate",
|
className: "notranslate",
|
||||||
reactComponent: Action,
|
reactComponent: Action,
|
||||||
props: { translator },
|
props: { translator, processActions },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggle(props) {
|
||||||
|
if (this.isVisible) {
|
||||||
|
document.dispatchEvent(
|
||||||
|
new CustomEvent(EVENT_KISS, {
|
||||||
|
detail: { action: MSG_POPUP_TOGGLE },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.show(props || this._props);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,47 @@
|
|||||||
export function touchTapListener(fn, touchsLength) {
|
export function touchTapListener(fn, options = {}) {
|
||||||
|
const config = {
|
||||||
|
taps: 2,
|
||||||
|
fingers: 1,
|
||||||
|
delay: 300,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
|
let maxTouches = 0;
|
||||||
|
let tapCount = 0;
|
||||||
|
let tapTimer = null;
|
||||||
|
|
||||||
|
const handleTouchStart = (e) => {
|
||||||
|
maxTouches = Math.max(maxTouches, e.touches.length);
|
||||||
|
};
|
||||||
|
|
||||||
const handleTouchend = (e) => {
|
const handleTouchend = (e) => {
|
||||||
if (e.touches.length === touchsLength) {
|
if (e.touches.length === 0) {
|
||||||
fn();
|
if (maxTouches === config.fingers) {
|
||||||
|
tapCount++;
|
||||||
|
clearTimeout(tapTimer);
|
||||||
|
|
||||||
|
if (tapCount === config.taps) {
|
||||||
|
fn(e);
|
||||||
|
tapCount = 0;
|
||||||
|
} else {
|
||||||
|
tapTimer = setTimeout(() => {
|
||||||
|
tapCount = 0;
|
||||||
|
}, config.delay);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tapCount = 0;
|
||||||
|
clearTimeout(tapTimer);
|
||||||
|
}
|
||||||
|
maxTouches = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("touchstart", handleTouchend);
|
document.addEventListener("touchstart", handleTouchStart, { passive: true });
|
||||||
|
document.addEventListener("touchend", handleTouchend, { passive: true });
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("touchstart", handleTouchend);
|
clearTimeout(tapTimer);
|
||||||
|
document.removeEventListener("touchstart", handleTouchStart);
|
||||||
|
document.removeEventListener("touchend", handleTouchend);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1644,6 +1644,17 @@ export class Translator {
|
|||||||
this.updateRule({ textStyle });
|
this.updateRule({ textStyle });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 切换划词翻译
|
||||||
|
toggleTransbox() {
|
||||||
|
this.#setting.tranboxSetting.transOpen =
|
||||||
|
!this.#setting.tranboxSetting.transOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换输入框翻译
|
||||||
|
toggleInputTranslate() {
|
||||||
|
this.#setting.inputRule.transOpen = !this.#setting.inputRule.transOpen;
|
||||||
|
}
|
||||||
|
|
||||||
// 停止运行
|
// 停止运行
|
||||||
stop() {
|
stop() {
|
||||||
this.disable();
|
this.disable();
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import { InputTranslator } from "./inputTranslate";
|
|||||||
import { TransboxManager } from "./tranbox";
|
import { TransboxManager } from "./tranbox";
|
||||||
import { shortcutRegister } from "./shortcut";
|
import { shortcutRegister } from "./shortcut";
|
||||||
import { sendIframeMsg } from "./iframe";
|
import { sendIframeMsg } from "./iframe";
|
||||||
import { newI18n } from "../config";
|
import { EVENT_KISS, newI18n } from "../config";
|
||||||
import { touchTapListener } from "./touch";
|
import { touchTapListener } from "./touch";
|
||||||
import { debounce } from "./utils";
|
|
||||||
import { PopupManager } from "./popupManager";
|
import { PopupManager } from "./popupManager";
|
||||||
import { FabManager } from "./fabManager";
|
import { FabManager } from "./fabManager";
|
||||||
import {
|
import {
|
||||||
@@ -20,6 +19,7 @@ import {
|
|||||||
MSG_TRANS_PUTRULE,
|
MSG_TRANS_PUTRULE,
|
||||||
MSG_OPEN_TRANBOX,
|
MSG_OPEN_TRANBOX,
|
||||||
MSG_TRANSBOX_TOGGLE,
|
MSG_TRANSBOX_TOGGLE,
|
||||||
|
MSG_POPUP_TOGGLE,
|
||||||
MSG_MOUSEHOVER_TOGGLE,
|
MSG_MOUSEHOVER_TOGGLE,
|
||||||
MSG_TRANSINPUT_TOGGLE,
|
MSG_TRANSINPUT_TOGGLE,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
@@ -57,16 +57,15 @@ export default class TranslatorManager {
|
|||||||
if (!isIframe) {
|
if (!isIframe) {
|
||||||
this._transboxManager = new TransboxManager(setting);
|
this._transboxManager = new TransboxManager(setting);
|
||||||
this._inputTranslator = new InputTranslator(setting);
|
this._inputTranslator = new InputTranslator(setting);
|
||||||
this._popupManager = new PopupManager({ translator: this._translator });
|
this._popupManager = new PopupManager({
|
||||||
|
translator: this._translator,
|
||||||
if (fabConfig && !fabConfig.isHide) {
|
processActions: this.#processActions.bind(this),
|
||||||
this._fabManager = new FabManager({
|
});
|
||||||
translator: this._translator,
|
this._fabManager = new FabManager({
|
||||||
popupManager: this._popupManager,
|
translator: this._translator,
|
||||||
fabConfig,
|
processActions: this.#processActions.bind(this),
|
||||||
});
|
fabConfig,
|
||||||
this._fabManager.show();
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#windowMessageHandler = this.#handleWindowMessage.bind(this);
|
this.#windowMessageHandler = this.#handleWindowMessage.bind(this);
|
||||||
@@ -125,8 +124,8 @@ export default class TranslatorManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 子模块
|
// 子模块
|
||||||
this._popupManager?.hide();
|
this._popupManager?.destroy();
|
||||||
this._fabManager?.hide();
|
this._fabManager?.destroy();
|
||||||
this._transboxManager?.disable();
|
this._transboxManager?.disable();
|
||||||
this._inputTranslator?.disable();
|
this._inputTranslator?.disable();
|
||||||
this._translator.stop();
|
this._translator.stop();
|
||||||
@@ -151,11 +150,39 @@ export default class TranslatorManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleTap = debounce(() => {
|
const handleTap = () => {
|
||||||
this.#processActions({ action: MSG_TRANS_TOGGLE });
|
this.#processActions({ action: MSG_TRANS_TOGGLE });
|
||||||
}, 300);
|
};
|
||||||
|
|
||||||
this.#clearTouchListener = touchTapListener(handleTap, touchTranslate);
|
switch (touchTranslate) {
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
this.#clearTouchListener = touchTapListener(handleTap, {
|
||||||
|
taps: 1,
|
||||||
|
fingers: touchTranslate,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
this.#clearTouchListener = touchTapListener(handleTap, {
|
||||||
|
taps: 2,
|
||||||
|
fingers: 1,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
this.#clearTouchListener = touchTapListener(handleTap, {
|
||||||
|
taps: 3,
|
||||||
|
fingers: 1,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
this.#clearTouchListener = touchTapListener(handleTap, {
|
||||||
|
taps: 2,
|
||||||
|
fingers: 2,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleWindowMessage(event) {
|
#handleWindowMessage(event) {
|
||||||
@@ -182,7 +209,7 @@ export default class TranslatorManager {
|
|||||||
this.#processActions({ action: MSG_TRANS_TOGGLE_STYLE })
|
this.#processActions({ action: MSG_TRANS_TOGGLE_STYLE })
|
||||||
),
|
),
|
||||||
shortcutRegister(shortcuts[OPT_SHORTCUT_POPUP], () =>
|
shortcutRegister(shortcuts[OPT_SHORTCUT_POPUP], () =>
|
||||||
this._popupManager.toggle()
|
this.#processActions({ action: MSG_POPUP_TOGGLE })
|
||||||
),
|
),
|
||||||
shortcutRegister(shortcuts[OPT_SHORTCUT_SETTING], () =>
|
shortcutRegister(shortcuts[OPT_SHORTCUT_SETTING], () =>
|
||||||
window.open(process.env.REACT_APP_OPTIONSPAGE, "_blank")
|
window.open(process.env.REACT_APP_OPTIONSPAGE, "_blank")
|
||||||
@@ -210,7 +237,7 @@ export default class TranslatorManager {
|
|||||||
),
|
),
|
||||||
GM.registerMenuCommand(
|
GM.registerMenuCommand(
|
||||||
i18n("open_menu"),
|
i18n("open_menu"),
|
||||||
() => this._popupManager.toggle(),
|
() => this.#processActions({ action: MSG_POPUP_TOGGLE }),
|
||||||
"K"
|
"K"
|
||||||
),
|
),
|
||||||
GM.registerMenuCommand(
|
GM.registerMenuCommand(
|
||||||
@@ -239,16 +266,25 @@ export default class TranslatorManager {
|
|||||||
this._translator.updateRule(args);
|
this._translator.updateRule(args);
|
||||||
break;
|
break;
|
||||||
case MSG_OPEN_TRANBOX:
|
case MSG_OPEN_TRANBOX:
|
||||||
this._transboxManager?.enable();
|
document.dispatchEvent(
|
||||||
|
new CustomEvent(EVENT_KISS, {
|
||||||
|
detail: { action: MSG_OPEN_TRANBOX },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case MSG_POPUP_TOGGLE:
|
||||||
|
this._popupManager?.toggle();
|
||||||
break;
|
break;
|
||||||
case MSG_TRANSBOX_TOGGLE:
|
case MSG_TRANSBOX_TOGGLE:
|
||||||
this._transboxManager?.toggle();
|
this._transboxManager?.toggle();
|
||||||
|
this._translator.toggleTransbox();
|
||||||
break;
|
break;
|
||||||
case MSG_MOUSEHOVER_TOGGLE:
|
case MSG_MOUSEHOVER_TOGGLE:
|
||||||
this._translator.toggleMouseHover();
|
this._translator.toggleMouseHover();
|
||||||
break;
|
break;
|
||||||
case MSG_TRANSINPUT_TOGGLE:
|
case MSG_TRANSINPUT_TOGGLE:
|
||||||
this._inputTranslator?.toggle();
|
this._inputTranslator?.toggle();
|
||||||
|
this._translator.toggleInputTranslate();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.info(`Message action is unavailable: ${action}`);
|
logger.info(`Message action is unavailable: ${action}`);
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import ThemeProvider from "../../hooks/Theme";
|
|||||||
import Draggable from "./Draggable";
|
import Draggable from "./Draggable";
|
||||||
import { useState, useMemo, useCallback } from "react";
|
import { useState, useMemo, useCallback } from "react";
|
||||||
import { SettingProvider } from "../../hooks/Setting";
|
import { SettingProvider } from "../../hooks/Setting";
|
||||||
import { MSG_TRANS_TOGGLE } from "../../config";
|
import { MSG_TRANS_TOGGLE, MSG_POPUP_TOGGLE } from "../../config";
|
||||||
import { sendIframeMsg } from "../../libs/iframe";
|
import { sendIframeMsg } from "../../libs/iframe";
|
||||||
import useWindowSize from "../../hooks/WindowSize";
|
import useWindowSize from "../../hooks/WindowSize";
|
||||||
|
|
||||||
export default function ContentFab({
|
export default function ContentFab({
|
||||||
translator,
|
translator,
|
||||||
fabConfig: { x: fabX, y: fabY, fabClickAction = 0 } = {},
|
fabConfig: { x: fabX, y: fabY, fabClickAction = 0 } = {},
|
||||||
popupManager,
|
processActions,
|
||||||
}) {
|
}) {
|
||||||
const fabWidth = 40;
|
const fabWidth = 40;
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
@@ -31,10 +31,10 @@ export default function ContentFab({
|
|||||||
translator.toggle();
|
translator.toggle();
|
||||||
sendIframeMsg(MSG_TRANS_TOGGLE);
|
sendIframeMsg(MSG_TRANS_TOGGLE);
|
||||||
} else {
|
} else {
|
||||||
popupManager.toggle();
|
processActions({ action: MSG_POPUP_TOGGLE });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [moved, translator, popupManager, fabClickAction]);
|
}, [moved, translator, fabClickAction, processActions]);
|
||||||
|
|
||||||
const fabProps = useMemo(
|
const fabProps = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@@ -1,27 +1,59 @@
|
|||||||
import ThemeProvider from "../../hooks/Theme";
|
import ThemeProvider from "../../hooks/Theme";
|
||||||
import Draggable from "./Draggable";
|
import Draggable from "./Draggable";
|
||||||
import { useEffect, useMemo, useCallback } from "react";
|
import { useEffect, useMemo, useCallback, useState } from "react";
|
||||||
import { SettingProvider } from "../../hooks/Setting";
|
import { SettingProvider } from "../../hooks/Setting";
|
||||||
import Popup from "../Popup";
|
|
||||||
import Header from "../Popup/Header";
|
import Header from "../Popup/Header";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Divider from "@mui/material/Divider";
|
import Divider from "@mui/material/Divider";
|
||||||
import useWindowSize from "../../hooks/WindowSize";
|
import useWindowSize from "../../hooks/WindowSize";
|
||||||
|
import { EVENT_KISS, MSG_OPEN_OPTIONS, MSG_POPUP_TOGGLE } from "../../config";
|
||||||
|
import PopupCont from "../Popup/PopupCont";
|
||||||
|
import { isExt } from "../../libs/client";
|
||||||
|
import { sendBgMsg } from "../../libs/msg";
|
||||||
|
|
||||||
export default function Action({ translator, onClose }) {
|
export default function Action({ translator, processActions }) {
|
||||||
|
const [showPopup, setShowPopup] = useState(true);
|
||||||
|
const [rule, setRule] = useState(translator.rule);
|
||||||
|
const [setting, setSetting] = useState(translator.setting);
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
|
|
||||||
const handleWindowClick = useCallback(() => {
|
const handleOpenSetting = useCallback(() => {
|
||||||
onClose();
|
if (isExt) {
|
||||||
}, [onClose]);
|
sendBgMsg(MSG_OPEN_OPTIONS);
|
||||||
|
} else {
|
||||||
|
window.open(process.env.REACT_APP_OPTIONSPAGE, "_blank");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const handleWindowClick = () => {
|
||||||
|
setShowPopup(false);
|
||||||
|
};
|
||||||
window.addEventListener("click", handleWindowClick);
|
window.addEventListener("click", handleWindowClick);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("click", handleWindowClick);
|
window.removeEventListener("click", handleWindowClick);
|
||||||
};
|
};
|
||||||
}, [handleWindowClick]);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleStatusUpdate = (event) => {
|
||||||
|
if (event.detail?.action === MSG_POPUP_TOGGLE) {
|
||||||
|
setShowPopup((pre) => !pre);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener(EVENT_KISS, handleStatusUpdate);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener(EVENT_KISS, handleStatusUpdate);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showPopup) {
|
||||||
|
setRule(translator.rule);
|
||||||
|
setSetting(translator.setting);
|
||||||
|
}
|
||||||
|
}, [showPopup, translator]);
|
||||||
|
|
||||||
const popProps = useMemo(() => {
|
const popProps = useMemo(() => {
|
||||||
const width = Math.min(windowSize.w, 360);
|
const width = Math.min(windowSize.w, 360);
|
||||||
@@ -40,19 +72,35 @@ export default function Action({ translator, onClose }) {
|
|||||||
return (
|
return (
|
||||||
<SettingProvider>
|
<SettingProvider>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<Draggable
|
{showPopup && (
|
||||||
key="pop"
|
<Draggable
|
||||||
{...popProps}
|
key="pop"
|
||||||
usePaper
|
{...popProps}
|
||||||
handler={
|
usePaper
|
||||||
<Box style={{ cursor: "move" }}>
|
handler={
|
||||||
<Header onClose={onClose} />
|
<Box style={{ cursor: "move" }}>
|
||||||
<Divider />
|
<Header
|
||||||
|
onClose={() => {
|
||||||
|
setShowPopup(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Divider />
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Box width={360}>
|
||||||
|
<PopupCont
|
||||||
|
rule={rule}
|
||||||
|
setting={setting}
|
||||||
|
setRule={setRule}
|
||||||
|
setSetting={setSetting}
|
||||||
|
handleOpenSetting={handleOpenSetting}
|
||||||
|
processActions={processActions}
|
||||||
|
isContent={true}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
</Draggable>
|
||||||
>
|
)}
|
||||||
<Popup translator={translator} />
|
|
||||||
</Draggable>
|
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</SettingProvider>
|
</SettingProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ export default function Settings() {
|
|||||||
label={i18n("touch_translate_shortcut")}
|
label={i18n("touch_translate_shortcut")}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
>
|
>
|
||||||
{[0, 2, 3, 4].map((item) => (
|
{[0, 2, 3, 4, 5, 6, 7].map((item) => (
|
||||||
<MenuItem key={item} value={item}>
|
<MenuItem key={item} value={item}>
|
||||||
{i18n(`touch_tap_${item}`)}
|
{i18n(`touch_tap_${item}`)}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|||||||
422
src/views/Popup/PopupCont.js
Normal file
422
src/views/Popup/PopupCont.js
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
import { useState, useEffect, useMemo } from "react";
|
||||||
|
import Stack from "@mui/material/Stack";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
|
import Switch from "@mui/material/Switch";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import Grid from "@mui/material/Grid";
|
||||||
|
import { sendBgMsg, sendTabMsg, getCurTab } from "../../libs/msg";
|
||||||
|
import { isExt } from "../../libs/client";
|
||||||
|
import { useI18n } from "../../hooks/I18n";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
import {
|
||||||
|
MSG_TRANS_TOGGLE,
|
||||||
|
MSG_TRANS_PUTRULE,
|
||||||
|
MSG_SAVE_RULE,
|
||||||
|
MSG_COMMAND_SHORTCUTS,
|
||||||
|
MSG_TRANSBOX_TOGGLE,
|
||||||
|
MSG_MOUSEHOVER_TOGGLE,
|
||||||
|
MSG_TRANSINPUT_TOGGLE,
|
||||||
|
OPT_LANGS_FROM,
|
||||||
|
OPT_LANGS_TO,
|
||||||
|
OPT_STYLE_ALL,
|
||||||
|
} from "../../config";
|
||||||
|
import { saveRule } from "../../libs/rules";
|
||||||
|
import { tryClearCaches } from "../../libs/cache";
|
||||||
|
import { kissLog } from "../../libs/log";
|
||||||
|
import { parseUrlPattern } from "../../libs/utils";
|
||||||
|
|
||||||
|
export default function PopupCont({
|
||||||
|
rule,
|
||||||
|
setting,
|
||||||
|
setRule,
|
||||||
|
setSetting,
|
||||||
|
handleOpenSetting,
|
||||||
|
processActions,
|
||||||
|
isContent = false,
|
||||||
|
}) {
|
||||||
|
const i18n = useI18n();
|
||||||
|
const [commands, setCommands] = useState({});
|
||||||
|
|
||||||
|
const handleTransToggle = async (e) => {
|
||||||
|
try {
|
||||||
|
setRule({ ...rule, transOpen: e.target.checked ? "true" : "false" });
|
||||||
|
|
||||||
|
if (!processActions) {
|
||||||
|
await sendTabMsg(MSG_TRANS_TOGGLE);
|
||||||
|
} else {
|
||||||
|
processActions({ action: MSG_TRANS_TOGGLE });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
kissLog("toggle trans", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTransboxToggle = async (e) => {
|
||||||
|
try {
|
||||||
|
setSetting((pre) => ({
|
||||||
|
...pre,
|
||||||
|
tranboxSetting: { ...pre.tranboxSetting, transOpen: e.target.checked },
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!processActions) {
|
||||||
|
await sendTabMsg(MSG_TRANSBOX_TOGGLE);
|
||||||
|
} else {
|
||||||
|
processActions({ action: MSG_TRANSBOX_TOGGLE });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
kissLog("toggle transbox", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMousehoverToggle = async (e) => {
|
||||||
|
try {
|
||||||
|
setSetting((pre) => ({
|
||||||
|
...pre,
|
||||||
|
mouseHoverSetting: {
|
||||||
|
...pre.mouseHoverSetting,
|
||||||
|
useMouseHover: e.target.checked,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!processActions) {
|
||||||
|
await sendTabMsg(MSG_MOUSEHOVER_TOGGLE);
|
||||||
|
} else {
|
||||||
|
processActions({ action: MSG_MOUSEHOVER_TOGGLE });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
kissLog("toggle mousehover", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputTransToggle = async (e) => {
|
||||||
|
try {
|
||||||
|
setSetting((pre) => ({
|
||||||
|
...pre,
|
||||||
|
inputRule: {
|
||||||
|
...pre.inputRule,
|
||||||
|
transOpen: e.target.checked,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!processActions) {
|
||||||
|
await sendTabMsg(MSG_TRANSINPUT_TOGGLE);
|
||||||
|
} else {
|
||||||
|
processActions({ action: MSG_TRANSINPUT_TOGGLE });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
kissLog("toggle inputtrans", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = async (e) => {
|
||||||
|
try {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setRule((pre) => ({ ...pre, [name]: value }));
|
||||||
|
|
||||||
|
if (!processActions) {
|
||||||
|
await sendTabMsg(MSG_TRANS_PUTRULE, { [name]: value });
|
||||||
|
} else {
|
||||||
|
processActions({ action: MSG_TRANS_PUTRULE, args: { [name]: value } });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
kissLog("update rule", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearCache = () => {
|
||||||
|
tryClearCaches();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveRule = async () => {
|
||||||
|
try {
|
||||||
|
let href = "";
|
||||||
|
if (!isContent) {
|
||||||
|
const tab = await getCurTab();
|
||||||
|
href = tab.url;
|
||||||
|
} else {
|
||||||
|
href = window.location?.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!href || typeof href !== "string") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = parseUrlPattern(href);
|
||||||
|
const curRule = { ...rule, pattern };
|
||||||
|
if (isExt && isContent) {
|
||||||
|
sendBgMsg(MSG_SAVE_RULE, curRule);
|
||||||
|
} else {
|
||||||
|
saveRule(curRule);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
kissLog("save rule", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const commands = {};
|
||||||
|
if (isExt) {
|
||||||
|
const res = await sendBgMsg(MSG_COMMAND_SHORTCUTS);
|
||||||
|
res.forEach(({ name, shortcut }) => {
|
||||||
|
commands[name] = shortcut;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const shortcuts = setting.shortcuts;
|
||||||
|
if (shortcuts) {
|
||||||
|
Object.entries(shortcuts).forEach(([key, val]) => {
|
||||||
|
commands[key] = val.join("+");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCommands(commands);
|
||||||
|
} catch (err) {
|
||||||
|
kissLog("query cmds", err);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [setting.shortcuts]);
|
||||||
|
|
||||||
|
const optApis = useMemo(
|
||||||
|
() =>
|
||||||
|
setting.transApis
|
||||||
|
.filter((api) => !api.isDisabled)
|
||||||
|
.map((api) => ({
|
||||||
|
key: api.apiSlug,
|
||||||
|
name: api.apiName || api.apiSlug,
|
||||||
|
})),
|
||||||
|
[setting.transApis]
|
||||||
|
);
|
||||||
|
|
||||||
|
const tranboxEnabled = setting.tranboxSetting.transOpen;
|
||||||
|
const mouseHoverEnabled = setting.mouseHoverSetting.useMouseHover;
|
||||||
|
const inputTransEnabled = setting.inputRule.transOpen;
|
||||||
|
|
||||||
|
const {
|
||||||
|
transOpen,
|
||||||
|
apiSlug,
|
||||||
|
fromLang,
|
||||||
|
toLang,
|
||||||
|
textStyle,
|
||||||
|
autoScan,
|
||||||
|
transOnly,
|
||||||
|
hasRichText,
|
||||||
|
hasShadowroot,
|
||||||
|
} = rule;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack sx={{ p: 2 }} spacing={2}>
|
||||||
|
<Grid container columns={12} spacing={1}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={transOpen === "true"}
|
||||||
|
onChange={handleTransToggle}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
commands["toggleTranslate"]
|
||||||
|
? `${i18n("translate_alt")}(${commands["toggleTranslate"]})`
|
||||||
|
: i18n("translate_alt")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
name="autoScan"
|
||||||
|
value={autoScan === "true" ? "false" : "true"}
|
||||||
|
checked={autoScan === "true"}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n("autoscan_alt")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
name="hasShadowroot"
|
||||||
|
value={hasShadowroot === "true" ? "false" : "true"}
|
||||||
|
checked={hasShadowroot === "true"}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n("shadowroot_alt")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
name="hasRichText"
|
||||||
|
value={hasRichText === "true" ? "false" : "true"}
|
||||||
|
checked={hasRichText === "true"}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n("richtext_alt")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
name="transOnly"
|
||||||
|
value={transOnly === "true" ? "false" : "true"}
|
||||||
|
checked={transOnly === "true"}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n("transonly_alt")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
name="tranboxEnabled"
|
||||||
|
value={!tranboxEnabled}
|
||||||
|
checked={tranboxEnabled}
|
||||||
|
onChange={handleTransboxToggle}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n("selection_translate")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
name="mouseHoverEnabled"
|
||||||
|
value={!mouseHoverEnabled}
|
||||||
|
checked={mouseHoverEnabled}
|
||||||
|
onChange={handleMousehoverToggle}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n("mousehover_translate")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
size="small"
|
||||||
|
name="inputTransEnabled"
|
||||||
|
value={!inputTransEnabled}
|
||||||
|
checked={inputTransEnabled}
|
||||||
|
onChange={handleInputTransToggle}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n("input_translate")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
select
|
||||||
|
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||||
|
size="small"
|
||||||
|
value={apiSlug}
|
||||||
|
name="apiSlug"
|
||||||
|
label={i18n("translate_service")}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
{optApis.map(({ key, name }) => (
|
||||||
|
<MenuItem key={key} value={key}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
select
|
||||||
|
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||||
|
size="small"
|
||||||
|
value={fromLang}
|
||||||
|
name="fromLang"
|
||||||
|
label={i18n("from_lang")}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
{OPT_LANGS_FROM.map(([lang, name]) => (
|
||||||
|
<MenuItem key={lang} value={lang}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
select
|
||||||
|
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||||
|
size="small"
|
||||||
|
value={toLang}
|
||||||
|
name="toLang"
|
||||||
|
label={i18n("to_lang")}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
{OPT_LANGS_TO.map(([lang, name]) => (
|
||||||
|
<MenuItem key={lang} value={lang}>
|
||||||
|
{name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
select
|
||||||
|
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||||
|
size="small"
|
||||||
|
value={textStyle}
|
||||||
|
name="textStyle"
|
||||||
|
label={
|
||||||
|
commands["toggleStyle"]
|
||||||
|
? `${i18n("text_style_alt")}(${commands["toggleStyle"]})`
|
||||||
|
: i18n("text_style_alt")
|
||||||
|
}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
{OPT_STYLE_ALL.map((item) => (
|
||||||
|
<MenuItem key={item} value={item}>
|
||||||
|
{i18n(item)}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
|
||||||
|
{/* {OPT_STYLE_USE_COLOR.includes(textStyle) && (
|
||||||
|
<TextField
|
||||||
|
size="small"
|
||||||
|
name="bgColor"
|
||||||
|
value={bgColor}
|
||||||
|
label={i18n("bg_color")}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
)} */}
|
||||||
|
|
||||||
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
spacing={2}
|
||||||
|
>
|
||||||
|
<Button variant="text" onClick={handleSaveRule}>
|
||||||
|
{i18n("save_rule")}
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" onClick={handleClearCache}>
|
||||||
|
{i18n("clear_cache")}
|
||||||
|
</Button>
|
||||||
|
<Button variant="text" onClick={handleOpenSetting}>
|
||||||
|
{i18n("setting")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,181 +1,26 @@
|
|||||||
import { useState, useEffect, useMemo } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Stack from "@mui/material/Stack";
|
import Stack from "@mui/material/Stack";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
|
||||||
import Switch from "@mui/material/Switch";
|
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Grid from "@mui/material/Grid";
|
import { sendTabMsg } from "../../libs/msg";
|
||||||
import { sendBgMsg, sendTabMsg, getCurTab } from "../../libs/msg";
|
|
||||||
import { browser } from "../../libs/browser";
|
import { browser } from "../../libs/browser";
|
||||||
import { isExt } from "../../libs/client";
|
|
||||||
import { useI18n } from "../../hooks/I18n";
|
import { useI18n } from "../../hooks/I18n";
|
||||||
import TextField from "@mui/material/TextField";
|
|
||||||
import Divider from "@mui/material/Divider";
|
import Divider from "@mui/material/Divider";
|
||||||
import Header from "./Header";
|
import Header from "./Header";
|
||||||
import {
|
import { MSG_TRANS_GETRULE } from "../../config";
|
||||||
MSG_TRANS_TOGGLE,
|
|
||||||
MSG_TRANS_GETRULE,
|
|
||||||
MSG_TRANS_PUTRULE,
|
|
||||||
MSG_OPEN_OPTIONS,
|
|
||||||
MSG_SAVE_RULE,
|
|
||||||
MSG_COMMAND_SHORTCUTS,
|
|
||||||
MSG_TRANSBOX_TOGGLE,
|
|
||||||
MSG_MOUSEHOVER_TOGGLE,
|
|
||||||
MSG_TRANSINPUT_TOGGLE,
|
|
||||||
OPT_LANGS_FROM,
|
|
||||||
OPT_LANGS_TO,
|
|
||||||
OPT_STYLE_ALL,
|
|
||||||
} from "../../config";
|
|
||||||
import { sendIframeMsg } from "../../libs/iframe";
|
|
||||||
import { saveRule } from "../../libs/rules";
|
|
||||||
import { tryClearCaches } from "../../libs/cache";
|
|
||||||
import { kissLog } from "../../libs/log";
|
import { kissLog } from "../../libs/log";
|
||||||
import { parseUrlPattern } from "../../libs/utils";
|
import PopupCont from "./PopupCont";
|
||||||
|
|
||||||
// 插件popup没有参数
|
export default function Popup() {
|
||||||
// 网页弹框有
|
|
||||||
export default function Popup({ translator }) {
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const [rule, setRule] = useState(translator?.rule);
|
const [rule, setRule] = useState(null);
|
||||||
const [setting, setSetting] = useState(translator?.setting);
|
const [setting, setSetting] = useState(null);
|
||||||
const [commands, setCommands] = useState({});
|
|
||||||
|
|
||||||
const handleOpenSetting = () => {
|
const handleOpenSetting = useCallback(() => {
|
||||||
if (!translator) {
|
browser?.runtime.openOptionsPage();
|
||||||
browser?.runtime.openOptionsPage();
|
}, []);
|
||||||
} else if (isExt) {
|
|
||||||
sendBgMsg(MSG_OPEN_OPTIONS);
|
|
||||||
} else {
|
|
||||||
window.open(process.env.REACT_APP_OPTIONSPAGE, "_blank");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTransToggle = async (e) => {
|
|
||||||
try {
|
|
||||||
setRule({ ...rule, transOpen: e.target.checked ? "true" : "false" });
|
|
||||||
|
|
||||||
if (!translator) {
|
|
||||||
await sendTabMsg(MSG_TRANS_TOGGLE);
|
|
||||||
} else {
|
|
||||||
translator.toggle();
|
|
||||||
sendIframeMsg(MSG_TRANS_TOGGLE);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
kissLog("toggle trans", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTransboxToggle = async (e) => {
|
|
||||||
try {
|
|
||||||
setSetting((pre) => ({
|
|
||||||
...pre,
|
|
||||||
tranboxSetting: { ...pre.tranboxSetting, transOpen: e.target.checked },
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (!translator) {
|
|
||||||
await sendTabMsg(MSG_TRANSBOX_TOGGLE);
|
|
||||||
} else {
|
|
||||||
translator.toggleTransbox();
|
|
||||||
sendIframeMsg(MSG_TRANSBOX_TOGGLE);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
kissLog("toggle transbox", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMousehoverToggle = async (e) => {
|
|
||||||
try {
|
|
||||||
setSetting((pre) => ({
|
|
||||||
...pre,
|
|
||||||
mouseHoverSetting: {
|
|
||||||
...pre.mouseHoverSetting,
|
|
||||||
useMouseHover: e.target.checked,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (!translator) {
|
|
||||||
await sendTabMsg(MSG_MOUSEHOVER_TOGGLE);
|
|
||||||
} else {
|
|
||||||
translator.toggleMouseHover();
|
|
||||||
sendIframeMsg(MSG_MOUSEHOVER_TOGGLE);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
kissLog("toggle mousehover", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInputTransToggle = async (e) => {
|
|
||||||
try {
|
|
||||||
setSetting((pre) => ({
|
|
||||||
...pre,
|
|
||||||
inputRule: {
|
|
||||||
...pre.inputRule,
|
|
||||||
transOpen: e.target.checked,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (!translator) {
|
|
||||||
await sendTabMsg(MSG_TRANSINPUT_TOGGLE);
|
|
||||||
} else {
|
|
||||||
translator.toggleInputTranslate();
|
|
||||||
sendIframeMsg(MSG_TRANSINPUT_TOGGLE);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
kissLog("toggle inputtrans", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = async (e) => {
|
|
||||||
try {
|
|
||||||
const { name, value } = e.target;
|
|
||||||
setRule((pre) => ({ ...pre, [name]: value }));
|
|
||||||
|
|
||||||
if (!translator) {
|
|
||||||
await sendTabMsg(MSG_TRANS_PUTRULE, { [name]: value });
|
|
||||||
} else {
|
|
||||||
translator.updateRule({ [name]: value });
|
|
||||||
sendIframeMsg(MSG_TRANS_PUTRULE, { [name]: value });
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
kissLog("update rule", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClearCache = () => {
|
|
||||||
tryClearCaches();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSaveRule = async () => {
|
|
||||||
try {
|
|
||||||
let href = "";
|
|
||||||
if (!translator) {
|
|
||||||
const tab = await getCurTab();
|
|
||||||
href = tab.url;
|
|
||||||
} else {
|
|
||||||
href = window.location?.href;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!href || typeof href !== "string") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pattern = parseUrlPattern(href);
|
|
||||||
const curRule = { ...rule, pattern };
|
|
||||||
if (isExt && translator) {
|
|
||||||
sendBgMsg(MSG_SAVE_RULE, curRule);
|
|
||||||
} else {
|
|
||||||
saveRule(curRule);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
kissLog("save rule", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (translator) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await sendTabMsg(MSG_TRANS_GETRULE);
|
const res = await sendTabMsg(MSG_TRANS_GETRULE);
|
||||||
@@ -187,297 +32,27 @@ export default function Popup({ translator }) {
|
|||||||
kissLog("query rule", err);
|
kissLog("query rule", err);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, [translator]);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
return (
|
||||||
(async () => {
|
<Box width={360}>
|
||||||
try {
|
<Header />
|
||||||
const commands = {};
|
<Divider />
|
||||||
if (isExt) {
|
{rule && setting ? (
|
||||||
const res = await sendBgMsg(MSG_COMMAND_SHORTCUTS);
|
<PopupCont
|
||||||
res.forEach(({ name, shortcut }) => {
|
rule={rule}
|
||||||
commands[name] = shortcut;
|
setting={setting}
|
||||||
});
|
setRule={setRule}
|
||||||
} else {
|
setSetting={setSetting}
|
||||||
const shortcuts = translator.setting.shortcuts;
|
handleOpenSetting={handleOpenSetting}
|
||||||
if (shortcuts) {
|
/>
|
||||||
Object.entries(shortcuts).forEach(([key, val]) => {
|
) : (
|
||||||
commands[key] = val.join("+");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCommands(commands);
|
|
||||||
} catch (err) {
|
|
||||||
kissLog("query cmds", err);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [translator]);
|
|
||||||
|
|
||||||
const optApis = useMemo(
|
|
||||||
() =>
|
|
||||||
setting?.transApis
|
|
||||||
.filter((api) => !api.isDisabled)
|
|
||||||
.map((api) => ({
|
|
||||||
key: api.apiSlug,
|
|
||||||
name: api.apiName || api.apiSlug,
|
|
||||||
})),
|
|
||||||
[setting]
|
|
||||||
);
|
|
||||||
|
|
||||||
const tranboxEnabled = setting?.tranboxSetting.transOpen;
|
|
||||||
const mouseHoverEnabled = setting?.mouseHoverSetting.useMouseHover;
|
|
||||||
const inputTransEnabled = setting?.inputRule.transOpen;
|
|
||||||
|
|
||||||
if (!rule) {
|
|
||||||
return (
|
|
||||||
<Box minWidth={360}>
|
|
||||||
{!translator && (
|
|
||||||
<>
|
|
||||||
<Header />
|
|
||||||
<Divider />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<Stack sx={{ p: 2 }} spacing={3}>
|
<Stack sx={{ p: 2 }} spacing={3}>
|
||||||
<Button variant="text" onClick={handleOpenSetting}>
|
<Button variant="text" onClick={handleOpenSetting}>
|
||||||
{i18n("setting")}
|
{i18n("setting")}
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
transOpen,
|
|
||||||
apiSlug,
|
|
||||||
fromLang,
|
|
||||||
toLang,
|
|
||||||
textStyle,
|
|
||||||
autoScan,
|
|
||||||
transOnly,
|
|
||||||
hasRichText,
|
|
||||||
hasShadowroot,
|
|
||||||
} = rule;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box width={360}>
|
|
||||||
{!translator && (
|
|
||||||
<>
|
|
||||||
<Header />
|
|
||||||
<Divider />
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
<Stack sx={{ p: 2 }} spacing={2}>
|
|
||||||
<Grid container columns={12} spacing={1}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
checked={transOpen === "true"}
|
|
||||||
onChange={handleTransToggle}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
commands["toggleTranslate"]
|
|
||||||
? `${i18n("translate_alt")}(${commands["toggleTranslate"]})`
|
|
||||||
: i18n("translate_alt")
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
name="autoScan"
|
|
||||||
value={autoScan === "true" ? "false" : "true"}
|
|
||||||
checked={autoScan === "true"}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n("autoscan_alt")}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
name="hasShadowroot"
|
|
||||||
value={hasShadowroot === "true" ? "false" : "true"}
|
|
||||||
checked={hasShadowroot === "true"}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n("shadowroot_alt")}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
name="hasRichText"
|
|
||||||
value={hasRichText === "true" ? "false" : "true"}
|
|
||||||
checked={hasRichText === "true"}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n("richtext_alt")}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
name="transOnly"
|
|
||||||
value={transOnly === "true" ? "false" : "true"}
|
|
||||||
checked={transOnly === "true"}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n("transonly_alt")}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
name="tranboxEnabled"
|
|
||||||
value={!tranboxEnabled}
|
|
||||||
checked={tranboxEnabled}
|
|
||||||
onChange={handleTransboxToggle}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n("selection_translate")}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
name="mouseHoverEnabled"
|
|
||||||
value={!mouseHoverEnabled}
|
|
||||||
checked={mouseHoverEnabled}
|
|
||||||
onChange={handleMousehoverToggle}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n("mousehover_translate")}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={6}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
size="small"
|
|
||||||
name="inputTransEnabled"
|
|
||||||
value={!inputTransEnabled}
|
|
||||||
checked={inputTransEnabled}
|
|
||||||
onChange={handleInputTransToggle}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n("input_translate")}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
select
|
|
||||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
|
||||||
size="small"
|
|
||||||
value={apiSlug}
|
|
||||||
name="apiSlug"
|
|
||||||
label={i18n("translate_service")}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
{optApis.map(({ key, name }) => (
|
|
||||||
<MenuItem key={key} value={key}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</TextField>
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
select
|
|
||||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
|
||||||
size="small"
|
|
||||||
value={fromLang}
|
|
||||||
name="fromLang"
|
|
||||||
label={i18n("from_lang")}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
{OPT_LANGS_FROM.map(([lang, name]) => (
|
|
||||||
<MenuItem key={lang} value={lang}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</TextField>
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
select
|
|
||||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
|
||||||
size="small"
|
|
||||||
value={toLang}
|
|
||||||
name="toLang"
|
|
||||||
label={i18n("to_lang")}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
{OPT_LANGS_TO.map(([lang, name]) => (
|
|
||||||
<MenuItem key={lang} value={lang}>
|
|
||||||
{name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</TextField>
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
select
|
|
||||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
|
||||||
size="small"
|
|
||||||
value={textStyle}
|
|
||||||
name="textStyle"
|
|
||||||
label={
|
|
||||||
commands["toggleStyle"]
|
|
||||||
? `${i18n("text_style_alt")}(${commands["toggleStyle"]})`
|
|
||||||
: i18n("text_style_alt")
|
|
||||||
}
|
|
||||||
onChange={handleChange}
|
|
||||||
>
|
|
||||||
{OPT_STYLE_ALL.map((item) => (
|
|
||||||
<MenuItem key={item} value={item}>
|
|
||||||
{i18n(item)}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</TextField>
|
|
||||||
|
|
||||||
{/* {OPT_STYLE_USE_COLOR.includes(textStyle) && (
|
|
||||||
<TextField
|
|
||||||
size="small"
|
|
||||||
name="bgColor"
|
|
||||||
value={bgColor}
|
|
||||||
label={i18n("bg_color")}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
)} */}
|
|
||||||
|
|
||||||
<Stack
|
|
||||||
direction="row"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
spacing={2}
|
|
||||||
>
|
|
||||||
<Button variant="text" onClick={handleSaveRule}>
|
|
||||||
{i18n("save_rule")}
|
|
||||||
</Button>
|
|
||||||
<Button variant="text" onClick={handleClearCache}>
|
|
||||||
{i18n("clear_cache")}
|
|
||||||
</Button>
|
|
||||||
<Button variant="text" onClick={handleOpenSetting}>
|
|
||||||
{i18n("setting")}
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { isMobile } from "../../libs/mobile";
|
|||||||
import TranForm from "./TranForm.js";
|
import TranForm from "./TranForm.js";
|
||||||
|
|
||||||
function Header({
|
function Header({
|
||||||
setShowPopup,
|
setShowBox,
|
||||||
simpleStyle,
|
simpleStyle,
|
||||||
setSimpleStyle,
|
setSimpleStyle,
|
||||||
hideClickAway,
|
hideClickAway,
|
||||||
@@ -98,7 +98,7 @@ function Header({
|
|||||||
<IconButton
|
<IconButton
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowPopup(false);
|
setShowBox(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseIcon fontSize="small" />
|
<CloseIcon fontSize="small" />
|
||||||
@@ -111,6 +111,7 @@ function Header({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function TranBox({
|
export default function TranBox({
|
||||||
|
showBox,
|
||||||
text,
|
text,
|
||||||
setText,
|
setText,
|
||||||
setShowBox,
|
setShowBox,
|
||||||
@@ -134,43 +135,45 @@ export default function TranBox({
|
|||||||
return (
|
return (
|
||||||
<SettingProvider>
|
<SettingProvider>
|
||||||
<ThemeProvider styles={extStyles}>
|
<ThemeProvider styles={extStyles}>
|
||||||
<DraggableResizable
|
{showBox && (
|
||||||
position={boxPosition}
|
<DraggableResizable
|
||||||
size={boxSize}
|
position={boxPosition}
|
||||||
setSize={setBoxSize}
|
size={boxSize}
|
||||||
setPosition={setBoxPosition}
|
setSize={setBoxSize}
|
||||||
header={
|
setPosition={setBoxPosition}
|
||||||
<Header
|
header={
|
||||||
setShowPopup={setShowBox}
|
<Header
|
||||||
simpleStyle={simpleStyle}
|
setShowBox={setShowBox}
|
||||||
setSimpleStyle={setSimpleStyle}
|
simpleStyle={simpleStyle}
|
||||||
hideClickAway={hideClickAway}
|
setSimpleStyle={setSimpleStyle}
|
||||||
setHideClickAway={setHideClickAway}
|
hideClickAway={hideClickAway}
|
||||||
followSelection={followSelection}
|
setHideClickAway={setHideClickAway}
|
||||||
setFollowSelection={setFollowSelection}
|
followSelection={followSelection}
|
||||||
mouseHover={mouseHover}
|
setFollowSelection={setFollowSelection}
|
||||||
/>
|
mouseHover={mouseHover}
|
||||||
}
|
/>
|
||||||
onClick={(e) => e.stopPropagation()}
|
}
|
||||||
onMouseEnter={() => setMouseHover(true)}
|
onClick={(e) => e.stopPropagation()}
|
||||||
onMouseLeave={() => setMouseHover(false)}
|
onMouseEnter={() => setMouseHover(true)}
|
||||||
>
|
onMouseLeave={() => setMouseHover(false)}
|
||||||
<Box sx={{ p: simpleStyle ? 1 : 2 }}>
|
>
|
||||||
<TranForm
|
<Box sx={{ p: simpleStyle ? 1 : 2 }}>
|
||||||
text={text}
|
<TranForm
|
||||||
setText={setText}
|
text={text}
|
||||||
apiSlugs={apiSlugs}
|
setText={setText}
|
||||||
fromLang={fromLang}
|
apiSlugs={apiSlugs}
|
||||||
toLang={toLang}
|
fromLang={fromLang}
|
||||||
toLang2={toLang2}
|
toLang={toLang}
|
||||||
transApis={transApis}
|
toLang2={toLang2}
|
||||||
simpleStyle={simpleStyle}
|
transApis={transApis}
|
||||||
langDetector={langDetector}
|
simpleStyle={simpleStyle}
|
||||||
enDict={enDict}
|
langDetector={langDetector}
|
||||||
enSug={enSug}
|
enDict={enDict}
|
||||||
/>
|
enSug={enSug}
|
||||||
</Box>
|
/>
|
||||||
</DraggableResizable>
|
</Box>
|
||||||
|
</DraggableResizable>
|
||||||
|
)}
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</SettingProvider>
|
</SettingProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
OPT_TRANBOX_TRIGGER_CLICK,
|
OPT_TRANBOX_TRIGGER_CLICK,
|
||||||
OPT_TRANBOX_TRIGGER_HOVER,
|
OPT_TRANBOX_TRIGGER_HOVER,
|
||||||
OPT_TRANBOX_TRIGGER_SELECT,
|
OPT_TRANBOX_TRIGGER_SELECT,
|
||||||
|
EVENT_KISS,
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { isMobile } from "../../libs/mobile";
|
import { isMobile } from "../../libs/mobile";
|
||||||
import { kissLog } from "../../libs/log";
|
import { kissLog } from "../../libs/log";
|
||||||
@@ -167,12 +168,26 @@ export default function Slection({
|
|||||||
};
|
};
|
||||||
}, [tranboxShortcut, handleTranbox]);
|
}, [tranboxShortcut, handleTranbox]);
|
||||||
|
|
||||||
|
const handleToggle = useCallback(() => {
|
||||||
|
if (showBox) {
|
||||||
|
setShowBox(false);
|
||||||
|
} else {
|
||||||
|
handleTranbox();
|
||||||
|
}
|
||||||
|
}, [showBox, handleTranbox]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener(MSG_OPEN_TRANBOX, handleTranbox);
|
const handleStatusUpdate = (event) => {
|
||||||
return () => {
|
if (event.detail?.action === MSG_OPEN_TRANBOX) {
|
||||||
window.removeEventListener(MSG_OPEN_TRANBOX, handleTranbox);
|
handleToggle();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [handleTranbox]);
|
|
||||||
|
document.addEventListener(EVENT_KISS, handleStatusUpdate);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener(EVENT_KISS, handleStatusUpdate);
|
||||||
|
};
|
||||||
|
}, [handleToggle]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isGm) {
|
if (!isGm) {
|
||||||
@@ -217,8 +232,9 @@ export default function Slection({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showBox && (
|
{
|
||||||
<TranBox
|
<TranBox
|
||||||
|
showBox={showBox}
|
||||||
text={text}
|
text={text}
|
||||||
setText={setText}
|
setText={setText}
|
||||||
boxSize={boxSize}
|
boxSize={boxSize}
|
||||||
@@ -237,7 +253,7 @@ export default function Slection({
|
|||||||
// extStyles={extStyles}
|
// extStyles={extStyles}
|
||||||
langDetector={langDetector}
|
langDetector={langDetector}
|
||||||
/>
|
/>
|
||||||
)}
|
}
|
||||||
|
|
||||||
{showBtn && (
|
{showBtn && (
|
||||||
<TranBtn
|
<TranBtn
|
||||||
|
|||||||
Reference in New Issue
Block a user