tranbox...
This commit is contained in:
@@ -114,7 +114,7 @@ export const apiTranslate = async ({
|
|||||||
OPT_LANGS_SPECIAL[translator].get(fromLang) ??
|
OPT_LANGS_SPECIAL[translator].get(fromLang) ??
|
||||||
OPT_LANGS_SPECIAL[translator].get("auto");
|
OPT_LANGS_SPECIAL[translator].get("auto");
|
||||||
const to = OPT_LANGS_SPECIAL[translator].get(toLang);
|
const to = OPT_LANGS_SPECIAL[translator].get(toLang);
|
||||||
if (!to) {
|
if (!text || !to) {
|
||||||
console.log(`[trans] target lang: ${toLang} not support`);
|
console.log(`[trans] target lang: ${toLang} not support`);
|
||||||
return [trText, isSame];
|
return [trText, isSame];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,10 @@ export async function showFab(translator) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showTransbox({ tranboxSetting = DEFAULT_TRANBOX_SETTING }) {
|
export function showTransbox({
|
||||||
|
tranboxSetting = DEFAULT_TRANBOX_SETTING,
|
||||||
|
transApis,
|
||||||
|
}) {
|
||||||
if (!tranboxSetting?.transOpen) {
|
if (!tranboxSetting?.transOpen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -99,7 +102,7 @@ export function showTransbox({ tranboxSetting = DEFAULT_TRANBOX_SETTING }) {
|
|||||||
ReactDOM.createRoot(shadowRootElement).render(
|
ReactDOM.createRoot(shadowRootElement).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<CacheProvider value={cache}>
|
<CacheProvider value={cache}>
|
||||||
<Slection tranboxSetting={tranboxSetting} />
|
<Slection tranboxSetting={tranboxSetting} transApis={transApis} />
|
||||||
</CacheProvider>
|
</CacheProvider>
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -623,12 +623,20 @@ export const I18N = {
|
|||||||
zh: `显示翻译框快捷键`,
|
zh: `显示翻译框快捷键`,
|
||||||
en: `Toggle Translate Box Shortcut`,
|
en: `Toggle Translate Box Shortcut`,
|
||||||
},
|
},
|
||||||
tanbtn_offset_x: {
|
tranbtn_offset_x: {
|
||||||
zh: `翻译按钮偏移(X)`,
|
zh: `翻译按钮偏移(X)`,
|
||||||
en: `Translate Button Offset (X)`,
|
en: `Translate Button Offset (X)`,
|
||||||
},
|
},
|
||||||
tanbtn_offset_y: {
|
tranbtn_offset_y: {
|
||||||
zh: `翻译按钮偏移(Y)`,
|
zh: `翻译按钮偏移(Y)`,
|
||||||
en: `Translate Button Offset (Y)`,
|
en: `Translate Button Offset (Y)`,
|
||||||
},
|
},
|
||||||
|
translated_text: {
|
||||||
|
zh: `译文`,
|
||||||
|
en: `Translated Text`,
|
||||||
|
},
|
||||||
|
original_text: {
|
||||||
|
zh: `原文`,
|
||||||
|
en: `Original Text`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -223,3 +223,13 @@ export const matchInputStr = (str, sign) => {
|
|||||||
}
|
}
|
||||||
return str.match(reg);
|
return str.match(reg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否英文单词
|
||||||
|
* @param {*} str
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const isValidWord = (str) => {
|
||||||
|
const regex = /^[a-zA-Z-]+$/;
|
||||||
|
return regex.test(str);
|
||||||
|
};
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export default function Tranbox() {
|
|||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
label={i18n("tanbtn_offset_x")}
|
label={i18n("tranbtn_offset_x")}
|
||||||
type="number"
|
type="number"
|
||||||
name="btnOffsetX"
|
name="btnOffsetX"
|
||||||
defaultValue={btnOffsetX}
|
defaultValue={btnOffsetX}
|
||||||
@@ -119,7 +119,7 @@ export default function Tranbox() {
|
|||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
label={i18n("tanbtn_offset_y")}
|
label={i18n("tranbtn_offset_y")}
|
||||||
type="number"
|
type="number"
|
||||||
name="btnOffsetY"
|
name="btnOffsetY"
|
||||||
defaultValue={btnOffsetY}
|
defaultValue={btnOffsetY}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
@@ -75,6 +75,7 @@ function Pointer({
|
|||||||
w = origin.w + dx;
|
w = origin.w + dx;
|
||||||
h = origin.h + dy;
|
h = origin.h + dy;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w < minSize.w) {
|
if (w < minSize.w) {
|
||||||
@@ -134,7 +135,8 @@ export default function DraggableResizable({
|
|||||||
w: 1200,
|
w: 1200,
|
||||||
h: 1200,
|
h: 1200,
|
||||||
},
|
},
|
||||||
sx,
|
onChangeSize,
|
||||||
|
onChangePosition,
|
||||||
}) {
|
}) {
|
||||||
const lineWidth = 4;
|
const lineWidth = 4;
|
||||||
const [position, setPosition] = useState(defaultPosition);
|
const [position, setPosition] = useState(defaultPosition);
|
||||||
@@ -149,6 +151,14 @@ export default function DraggableResizable({
|
|||||||
maxSize,
|
maxSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onChangeSize && onChangeSize(size);
|
||||||
|
}, [size, onChangeSize]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onChangePosition && onChangePosition(position);
|
||||||
|
}, [position, onChangePosition]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
@@ -158,7 +168,7 @@ export default function DraggableResizable({
|
|||||||
display: "grid",
|
display: "grid",
|
||||||
gridTemplateColumns: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
gridTemplateColumns: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
||||||
gridTemplateRows: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
gridTemplateRows: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
||||||
zIndex: 10000,
|
zIndex: 2147483647,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Pointer
|
<Pointer
|
||||||
|
|||||||
@@ -8,21 +8,139 @@ import MenuItem from "@mui/material/MenuItem";
|
|||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
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 Alert from "@mui/material/Alert";
|
||||||
|
import CircularProgress from "@mui/material/CircularProgress";
|
||||||
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,
|
||||||
|
DEFAULT_TRANS_APIS,
|
||||||
|
OPT_TRANS_BAIDU,
|
||||||
|
} from "../../config";
|
||||||
|
import { useEffect, useState, useRef } from "react";
|
||||||
|
import { apiTranslate } from "../../apis";
|
||||||
|
import { isValidWord } from "../../libs/utils";
|
||||||
|
|
||||||
function TranForm({ tranboxSetting }) {
|
const exchangeMap = {
|
||||||
|
word_third: "第三人称单数",
|
||||||
|
word_ing: "现在分词",
|
||||||
|
word_done: "过去式",
|
||||||
|
word_past: "过去分词",
|
||||||
|
word_pl: "复数",
|
||||||
|
word_proto: "原词",
|
||||||
|
};
|
||||||
|
|
||||||
|
function DictCont({ dictResult }) {
|
||||||
|
if (!dictResult) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<h4>{dictResult.simple_means?.word_name}</h4>
|
||||||
|
<p>
|
||||||
|
{Object.entries(dictResult.simple_means?.exchange || {}).map(
|
||||||
|
([key, val]) => (
|
||||||
|
<span key={key}>{`${exchangeMap[key] || key}: ${val.join(
|
||||||
|
","
|
||||||
|
)}; `}</span>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{Object.values(dictResult.simple_means?.tags || {})
|
||||||
|
.map((vals) => vals.join(", "))
|
||||||
|
.join(", ")}
|
||||||
|
</p>
|
||||||
|
{dictResult.simple_means?.symbols?.map(({ ph_en, ph_am, parts }, idx) => (
|
||||||
|
<div key={idx}>
|
||||||
|
<p>{`英: [${ph_en}] 美: [${ph_am}]`}</p>
|
||||||
|
{parts.map(({ part, means }, idx) => (
|
||||||
|
<p key={idx}>{`[${part}]: ${means.join("; ")}`}</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TranCont({ text, translator, fromLang, toLang, transApis }) {
|
||||||
|
const i18n = useI18n();
|
||||||
|
const [trText, setTrText] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
const [dictResult, setDictResult] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
setTrText("");
|
||||||
|
setError("");
|
||||||
|
setDictResult(null);
|
||||||
|
|
||||||
|
const apis = { ...transApis, ...DEFAULT_TRANS_APIS };
|
||||||
|
const apiSetting = apis[translator];
|
||||||
|
const tranRes = await apiTranslate({
|
||||||
|
text,
|
||||||
|
translator,
|
||||||
|
fromLang,
|
||||||
|
toLang,
|
||||||
|
apiSetting,
|
||||||
|
});
|
||||||
|
setTrText(tranRes[0]);
|
||||||
|
|
||||||
|
// 词典
|
||||||
|
if (isValidWord(text) && toLang.startsWith("zh")) {
|
||||||
|
if (fromLang === "en" && translator === OPT_TRANS_BAIDU) {
|
||||||
|
setDictResult(tranRes[2]);
|
||||||
|
} else {
|
||||||
|
const dictRes = await apiTranslate({
|
||||||
|
text,
|
||||||
|
translator: OPT_TRANS_BAIDU,
|
||||||
|
fromLang: "en",
|
||||||
|
toLang: "zh-CN",
|
||||||
|
apiSetting: apis[OPT_TRANS_BAIDU],
|
||||||
|
});
|
||||||
|
setDictResult(dictRes[2].dict_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setError(err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [text, translator, fromLang, toLang, transApis]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box>
|
||||||
|
<TextField
|
||||||
|
label={i18n("translated_text")}
|
||||||
|
fullWidth
|
||||||
|
multiline
|
||||||
|
value={trText}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{loading && <CircularProgress size={24} />}
|
||||||
|
{error && <Alert severity="error">{error}</Alert>}
|
||||||
|
{dictResult && <DictCont dictResult={dictResult} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TranForm({ text, setText, tranboxSetting, transApis }) {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
|
|
||||||
const {
|
const [editMode, setEditMode] = useState(false);
|
||||||
transOpen,
|
const [editText, setEditText] = useState("");
|
||||||
translator,
|
const [translator, setTranslator] = useState(tranboxSetting.translator);
|
||||||
fromLang,
|
const [fromLang, setFromLang] = useState(tranboxSetting.fromLang);
|
||||||
toLang,
|
const [toLang, setToLang] = useState(tranboxSetting.toLang);
|
||||||
tranboxShortcut,
|
const inputRef = useRef(null);
|
||||||
btnOffsetX,
|
|
||||||
btnOffsetY,
|
|
||||||
} = tranboxSetting;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack sx={{ p: 2 }} spacing={2}>
|
<Stack sx={{ p: 2 }} spacing={2}>
|
||||||
@@ -37,7 +155,9 @@ function TranForm({ tranboxSetting }) {
|
|||||||
name="fromLang"
|
name="fromLang"
|
||||||
value={fromLang}
|
value={fromLang}
|
||||||
label={i18n("from_lang")}
|
label={i18n("from_lang")}
|
||||||
// onChange={handleChange}
|
onChange={(e) => {
|
||||||
|
setFromLang(e.target.value);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{OPT_LANGS_FROM.map(([lang, name]) => (
|
{OPT_LANGS_FROM.map(([lang, name]) => (
|
||||||
<MenuItem key={lang} value={lang}>
|
<MenuItem key={lang} value={lang}>
|
||||||
@@ -55,7 +175,9 @@ function TranForm({ tranboxSetting }) {
|
|||||||
name="toLang"
|
name="toLang"
|
||||||
value={toLang}
|
value={toLang}
|
||||||
label={i18n("to_lang")}
|
label={i18n("to_lang")}
|
||||||
// onChange={handleChange}
|
onChange={(e) => {
|
||||||
|
setToLang(e.target.value);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{OPT_LANGS_TO.map(([lang, name]) => (
|
{OPT_LANGS_TO.map(([lang, name]) => (
|
||||||
<MenuItem key={lang} value={lang}>
|
<MenuItem key={lang} value={lang}>
|
||||||
@@ -73,7 +195,9 @@ function TranForm({ tranboxSetting }) {
|
|||||||
value={translator}
|
value={translator}
|
||||||
name="translator"
|
name="translator"
|
||||||
label={i18n("translate_service")}
|
label={i18n("translate_service")}
|
||||||
// onChange={handleChange}
|
onChange={(e) => {
|
||||||
|
setTranslator(e.target.value);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{OPT_TRANS_ALL.map((item) => (
|
{OPT_TRANS_ALL.map((item) => (
|
||||||
<MenuItem key={item} value={item}>
|
<MenuItem key={item} value={item}>
|
||||||
@@ -84,20 +208,72 @@ function TranForm({ tranboxSetting }) {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<TextField
|
||||||
|
label={i18n("original_text")}
|
||||||
|
inputRef={inputRef}
|
||||||
|
fullWidth
|
||||||
|
multiline
|
||||||
|
value={editMode ? editText : text}
|
||||||
|
disabled={!editMode}
|
||||||
|
onChange={(e) => {
|
||||||
|
setEditText(e.target.value);
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setEditMode(true);
|
||||||
|
setEditText(text);
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
inputRef.current?.focus();
|
||||||
|
}, 100);
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
setEditMode(false);
|
||||||
|
setText(editText.trim());
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<TranCont
|
||||||
|
text={text}
|
||||||
|
translator={translator}
|
||||||
|
fromLang={fromLang}
|
||||||
|
toLang={toLang}
|
||||||
|
transApis={transApis}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TranBox({ position, setShowBox, tranboxSetting }) {
|
export default function TranBox({
|
||||||
|
text,
|
||||||
|
setText,
|
||||||
|
setShowBox,
|
||||||
|
tranboxSetting,
|
||||||
|
transApis,
|
||||||
|
boxSize,
|
||||||
|
setBoxSize,
|
||||||
|
boxPosition,
|
||||||
|
setBoxPosition,
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<SettingProvider>
|
<SettingProvider>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<DraggableResizable
|
<DraggableResizable
|
||||||
defaultPosition={position}
|
defaultPosition={boxPosition}
|
||||||
|
defaultSize={boxSize}
|
||||||
header={<Header setShowPopup={setShowBox} />}
|
header={<Header setShowPopup={setShowBox} />}
|
||||||
|
onChangeSize={setBoxSize}
|
||||||
|
onChangePosition={setBoxPosition}
|
||||||
>
|
>
|
||||||
<Divider />
|
<Divider />
|
||||||
<TranForm tranboxSetting={tranboxSetting} />
|
<TranForm
|
||||||
|
text={text}
|
||||||
|
setText={setText}
|
||||||
|
tranboxSetting={tranboxSetting}
|
||||||
|
transApis={transApis}
|
||||||
|
/>
|
||||||
</DraggableResizable>
|
</DraggableResizable>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</SettingProvider>
|
</SettingProvider>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export default function TranBtn({ onClick, position, tranboxSetting }) {
|
|||||||
position: "fixed",
|
position: "fixed",
|
||||||
left: position.x + tranboxSetting.btnOffsetX,
|
left: position.x + tranboxSetting.btnOffsetX,
|
||||||
top: position.y + tranboxSetting.btnOffsetY,
|
top: position.y + tranboxSetting.btnOffsetY,
|
||||||
|
zIndex: 2147483647,
|
||||||
}}
|
}}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onMouseUp={(e) => {
|
onMouseUp={(e) => {
|
||||||
|
|||||||
@@ -1,26 +1,38 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import TranBtn from "./Tranbtn";
|
import TranBtn from "./Tranbtn";
|
||||||
import TranBox from "./Tranbox";
|
import TranBox from "./Tranbox";
|
||||||
|
import { shortcutRegister } from "../../libs/shortcut";
|
||||||
|
|
||||||
export default function Slection({ tranboxSetting }) {
|
export default function Slection({ tranboxSetting, transApis }) {
|
||||||
const [showBox, setShowBox] = useState(false);
|
const [showBox, setShowBox] = useState(false);
|
||||||
const [showBtn, setShowBtn] = useState(false);
|
const [showBtn, setShowBtn] = useState(false);
|
||||||
|
const [selectedText, setSelText] = useState("");
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const [position, setPosition] = useState({ x: 0, y: 0 });
|
const [position, setPosition] = useState({ x: 0, y: 0 });
|
||||||
|
const [boxSize, setBoxSize] = useState({ w: 600, h: 400 });
|
||||||
console.log("tranboxSetting", tranboxSetting);
|
const [boxPosition, setBoxPosition] = useState({
|
||||||
|
x: (window.innerWidth - 600) / 2,
|
||||||
|
y: (window.innerHeight - 400) / 2,
|
||||||
|
});
|
||||||
|
|
||||||
function handleMouseup(e) {
|
function handleMouseup(e) {
|
||||||
const text = window.getSelection()?.toString()?.trim() || "";
|
const selectedText = window.getSelection()?.toString()?.trim() || "";
|
||||||
|
if (!selectedText) {
|
||||||
|
setShowBtn(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelText(selectedText);
|
||||||
|
setShowBtn(true);
|
||||||
setPosition({ x: e.clientX, y: e.clientY });
|
setPosition({ x: e.clientX, y: e.clientY });
|
||||||
setText(text);
|
|
||||||
setShowBtn(!!text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClick = (e) => {
|
const handleClick = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setShowBtn(false);
|
setShowBtn(false);
|
||||||
if (!!text) {
|
|
||||||
|
setText(selectedText);
|
||||||
|
if (!showBox) {
|
||||||
setShowBox(true);
|
setShowBox(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -32,12 +44,31 @@ export default function Slection({ tranboxSetting }) {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const clearShortcut = shortcutRegister(
|
||||||
|
tranboxSetting.tranboxShortcut,
|
||||||
|
() => {
|
||||||
|
setShowBox((pre) => !pre);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearShortcut();
|
||||||
|
};
|
||||||
|
}, [tranboxSetting.tranboxShortcut, setShowBox]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showBox && (
|
{showBox && (
|
||||||
<TranBox
|
<TranBox
|
||||||
position={position}
|
text={text}
|
||||||
|
setText={setText}
|
||||||
|
boxSize={boxSize}
|
||||||
|
setBoxSize={setBoxSize}
|
||||||
|
boxPosition={boxPosition}
|
||||||
|
setBoxPosition={setBoxPosition}
|
||||||
tranboxSetting={tranboxSetting}
|
tranboxSetting={tranboxSetting}
|
||||||
|
transApis={transApis}
|
||||||
setShowBox={setShowBox}
|
setShowBox={setShowBox}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user