feat: support youdao dict
This commit is contained in:
@@ -1,81 +1,40 @@
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import FavBtn from "./FavBtn";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import AudioBtn from "./AudioBtn";
|
||||
import CircularProgress from "@mui/material/CircularProgress";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import Alert from "@mui/material/Alert";
|
||||
import { OPT_TRANS_BAIDU, PHONIC_MAP } from "../../config";
|
||||
import { apiTranslate } from "../../apis";
|
||||
import { isValidWord } from "../../libs/utils";
|
||||
import { OPT_DICT_BAIDU, OPT_DICT_YOUDAO, PHONIC_MAP } from "../../config";
|
||||
import CopyBtn from "./CopyBtn";
|
||||
import { useAsyncNow } from "../../hooks/Fetch";
|
||||
import { apiYoudaoDict } from "../../apis";
|
||||
|
||||
function DictBaidu({ text, setCopyText }) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState("");
|
||||
const [dictResult, setDictResult] = useState(null);
|
||||
// useEffect(() => {
|
||||
// if (!data) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError("");
|
||||
setDictResult(null);
|
||||
// const copyText = [
|
||||
// data.src,
|
||||
// data.voice
|
||||
// ?.map(Object.entries)
|
||||
// .map((item) => item[0])
|
||||
// .map(([key, val]) => `${PHONIC_MAP[key]?.[0] || key} ${val}`)
|
||||
// .join(" "),
|
||||
// data.content[0].mean
|
||||
// .map(({ pre, cont }) => {
|
||||
// return `${pre ? `[${pre}] ` : ""}${Object.keys(cont).join("; ")}`;
|
||||
// })
|
||||
// .join("\n"),
|
||||
// ].join("\n");
|
||||
|
||||
// if (!isValidWord(text)) {
|
||||
// return;
|
||||
// }
|
||||
// setCopyText(copyText);
|
||||
// }, [data, setCopyText]);
|
||||
|
||||
// // todo: 修复
|
||||
// const dictRes = await apiTranslate({
|
||||
// text,
|
||||
// apiSlug: OPT_TRANS_BAIDU,
|
||||
// fromLang: "en",
|
||||
// toLang: "zh-CN",
|
||||
// });
|
||||
|
||||
// if (dictRes[2]?.type === 1) {
|
||||
// setDictResult(JSON.parse(dictRes[2].result));
|
||||
// }
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
})();
|
||||
}, [text]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!dictResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
const copyText = [
|
||||
dictResult.src,
|
||||
dictResult.voice
|
||||
?.map(Object.entries)
|
||||
.map((item) => item[0])
|
||||
.map(([key, val]) => `${PHONIC_MAP[key]?.[0] || key} ${val}`)
|
||||
.join(" "),
|
||||
dictResult.content[0].mean
|
||||
.map(({ pre, cont }) => {
|
||||
return `${pre ? `[${pre}] ` : ""}${Object.keys(cont).join("; ")}`;
|
||||
})
|
||||
.join("\n"),
|
||||
].join("\n");
|
||||
|
||||
setCopyText(copyText);
|
||||
}, [dictResult, setCopyText]);
|
||||
|
||||
if (loading) {
|
||||
return <CircularProgress size={16} />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <Alert severity="error">{error}</Alert>;
|
||||
}
|
||||
|
||||
return <Typography>baidu: {text}</Typography>;
|
||||
return <Typography>baidu dict not supported yet</Typography>;
|
||||
|
||||
{
|
||||
/* {dictResult && (
|
||||
@@ -109,11 +68,56 @@ function DictBaidu({ text, setCopyText }) {
|
||||
}
|
||||
}
|
||||
|
||||
function DictYoudao({ text, setCopyText }) {
|
||||
const { loading, error, data } = useAsyncNow(apiYoudaoDict, text);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const copyText = [
|
||||
text,
|
||||
data?.ec?.word?.trs
|
||||
?.map(({ pos, tran }) => `${pos ? `[${pos}] ` : ""}${tran}`)
|
||||
.join("\n"),
|
||||
].join("\n");
|
||||
|
||||
setCopyText(copyText);
|
||||
}, [data, setCopyText]);
|
||||
|
||||
if (loading) {
|
||||
return <CircularProgress size={16} />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <Alert severity="error">{error}</Alert>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography component="div">
|
||||
<Typography component="ul">
|
||||
{data?.ec?.word?.trs?.map(({ pos, tran }, idx) => (
|
||||
<Typography component="li" key={idx}>
|
||||
{pos && `[${pos}] `}
|
||||
{tran}
|
||||
</Typography>
|
||||
))}
|
||||
</Typography>
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DictCont({ text, enDict }) {
|
||||
const [copyText, setCopyText] = useState(text);
|
||||
|
||||
const dictMap = {
|
||||
[OPT_TRANS_BAIDU]: <DictBaidu text={text} setCopyText={setCopyText} />,
|
||||
[OPT_DICT_BAIDU]: <DictBaidu text={text} setCopyText={setCopyText} />,
|
||||
[OPT_DICT_YOUDAO]: <DictYoudao text={text} setCopyText={setCopyText} />,
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -130,6 +134,8 @@ export default function DictCont({ text, enDict }) {
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
<Divider />
|
||||
|
||||
{dictMap[enDict] || <Typography>Dict not support</Typography>}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { apiBaiduSuggest } from "../../apis";
|
||||
import CircularProgress from "@mui/material/CircularProgress";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import Alert from "@mui/material/Alert";
|
||||
import { apiBaiduSuggest, apiYoudaoSuggest } from "../../apis";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import { OPT_SUG_BAIDU, OPT_SUG_YOUDAO } from "../../config";
|
||||
import { useAsyncNow } from "../../hooks/Fetch";
|
||||
|
||||
export default function SugCont({ text }) {
|
||||
const [sugs, setSugs] = useState([]);
|
||||
function SugBaidu({ text }) {
|
||||
const { loading, error, data } = useAsyncNow(apiBaiduSuggest, text);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
setSugs(await apiBaiduSuggest(text));
|
||||
} catch (err) {
|
||||
// skip
|
||||
}
|
||||
})();
|
||||
}, [text]);
|
||||
if (loading) {
|
||||
return <CircularProgress size={16} />;
|
||||
}
|
||||
|
||||
if (sugs.length === 0) {
|
||||
return;
|
||||
if (error) {
|
||||
return <Alert severity="error">{error}</Alert>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack spacing={1}>
|
||||
{sugs.map(({ k, v }) => (
|
||||
<>
|
||||
{data.map(({ k, v }) => (
|
||||
<Typography component="div" key={k}>
|
||||
<Typography>{k}</Typography>
|
||||
<Typography component="ul" style={{ margin: "0" }}>
|
||||
@@ -30,6 +32,49 @@ export default function SugCont({ text }) {
|
||||
</Typography>
|
||||
</Typography>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function SugYoudao({ text }) {
|
||||
const { loading, error, data } = useAsyncNow(apiYoudaoSuggest, text);
|
||||
|
||||
if (loading) {
|
||||
return <CircularProgress size={16} />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <Alert severity="error">{error}</Alert>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{data.map(({ entry, explain }) => (
|
||||
<Typography component="div" key={entry}>
|
||||
<Typography>{entry}</Typography>
|
||||
<Typography component="ul" style={{ margin: "0" }}>
|
||||
<Typography component="li">{explain}</Typography>
|
||||
</Typography>
|
||||
</Typography>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default function SugCont({ text, enSug }) {
|
||||
const sugMap = {
|
||||
[OPT_SUG_BAIDU]: <SugBaidu text={text} />,
|
||||
[OPT_SUG_YOUDAO]: <SugYoudao text={text} />,
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack spacing={1}>
|
||||
<Divider />
|
||||
{sugMap[enSug] || <Typography>Sug not support</Typography>}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ export default function TranBox({
|
||||
text,
|
||||
setText,
|
||||
setShowBox,
|
||||
tranboxSetting: { apiSlugs, fromLang, toLang, toLang2 },
|
||||
tranboxSetting: { enDict, enSug, apiSlugs, fromLang, toLang, toLang2 },
|
||||
transApis,
|
||||
boxSize,
|
||||
setBoxSize,
|
||||
@@ -128,7 +128,6 @@ export default function TranBox({
|
||||
setFollowSelection,
|
||||
extStyles = "",
|
||||
langDetector,
|
||||
enDict,
|
||||
}) {
|
||||
const [mouseHover, setMouseHover] = useState(false);
|
||||
// todo: 这里的 SettingProvider 不应和 background 的共用
|
||||
@@ -168,6 +167,7 @@ export default function TranBox({
|
||||
simpleStyle={simpleStyle}
|
||||
langDetector={langDetector}
|
||||
enDict={enDict}
|
||||
enSug={enSug}
|
||||
/>
|
||||
</Box>
|
||||
</DraggableResizable>
|
||||
|
||||
@@ -12,8 +12,10 @@ import {
|
||||
OPT_LANGS_TO,
|
||||
OPT_LANGDETECTOR_ALL,
|
||||
OPT_DICT_ALL,
|
||||
OPT_SUG_ALL,
|
||||
OPT_LANGS_MAP,
|
||||
OPT_DICT_MAP,
|
||||
OPT_SUG_MAP,
|
||||
} from "../../config";
|
||||
import { useState, useMemo, useEffect } from "react";
|
||||
import TranCont from "./TranCont";
|
||||
@@ -30,11 +32,12 @@ export default function TranForm({
|
||||
apiSlugs: initApiSlugs,
|
||||
fromLang: initFromLang,
|
||||
toLang: initToLang,
|
||||
toLang2,
|
||||
toLang2: initToLang2,
|
||||
transApis,
|
||||
simpleStyle = false,
|
||||
langDetector: initLangDetector = "-",
|
||||
enDict: initEnDict = "-",
|
||||
enSug: initEnSug = "-",
|
||||
isPlaygound = false,
|
||||
}) {
|
||||
const i18n = useI18n();
|
||||
@@ -44,11 +47,19 @@ export default function TranForm({
|
||||
const [apiSlugs, setApiSlugs] = useState(initApiSlugs);
|
||||
const [fromLang, setFromLang] = useState(initFromLang);
|
||||
const [toLang, setToLang] = useState(initToLang);
|
||||
const [toLang2, setToLang2] = useState(initToLang2);
|
||||
const [langDetector, setLangDetector] = useState(initLangDetector);
|
||||
const [enDict, setEnDict] = useState(initEnDict);
|
||||
const [enSug, setEnSug] = useState(initEnSug);
|
||||
const [deLang, setDeLang] = useState("");
|
||||
const [deLoading, setDeLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!editMode) {
|
||||
setEditText(text);
|
||||
}
|
||||
}, [text, editMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!text.trim()) {
|
||||
setDeLang("");
|
||||
@@ -96,6 +107,7 @@ export default function TranForm({
|
||||
);
|
||||
|
||||
const isWord = useMemo(() => isValidWord(text), [text]);
|
||||
const xs = useMemo(() => (isPlaygound ? 3 : 4), [isPlaygound]);
|
||||
|
||||
return (
|
||||
<Stack spacing={simpleStyle ? 1 : 2}>
|
||||
@@ -103,18 +115,18 @@ export default function TranForm({
|
||||
<>
|
||||
<Box>
|
||||
<Grid container spacing={2} columns={12}>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{
|
||||
multiple: true,
|
||||
MenuProps: { disablePortal: true },
|
||||
MenuProps: { disablePortal: !isPlaygound },
|
||||
}}
|
||||
fullWidth
|
||||
size="small"
|
||||
value={apiSlugs}
|
||||
name="apiSlugs"
|
||||
label={i18n("translate_service")}
|
||||
label={i18n("translate_service_multiple")}
|
||||
onChange={(e) => {
|
||||
setApiSlugs(e.target.value);
|
||||
}}
|
||||
@@ -126,10 +138,10 @@ export default function TranForm({
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||
SelectProps={{ MenuProps: { disablePortal: !isPlaygound } }}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="fromLang"
|
||||
@@ -146,10 +158,10 @@ export default function TranForm({
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||
SelectProps={{ MenuProps: { disablePortal: !isPlaygound } }}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="toLang"
|
||||
@@ -166,73 +178,120 @@ export default function TranForm({
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
|
||||
{isPlaygound && (
|
||||
<>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{
|
||||
MenuProps: { disablePortal: !isPlaygound },
|
||||
}}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="toLang2"
|
||||
value={toLang2}
|
||||
label={i18n("to_lang2")}
|
||||
onChange={(e) => {
|
||||
setToLang2(e.target.value);
|
||||
}}
|
||||
>
|
||||
{OPT_LANGS_TO.map(([lang, name]) => (
|
||||
<MenuItem key={lang} value={lang}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{
|
||||
MenuProps: { disablePortal: !isPlaygound },
|
||||
}}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="enDict"
|
||||
value={enDict}
|
||||
label={i18n("english_dict")}
|
||||
onChange={(e) => {
|
||||
setEnDict(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={"-"}>{i18n("disable")}</MenuItem>
|
||||
{OPT_DICT_ALL.map((item) => (
|
||||
<MenuItem value={item} key={item}>
|
||||
{item}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{
|
||||
MenuProps: { disablePortal: !isPlaygound },
|
||||
}}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="enSug"
|
||||
value={enSug}
|
||||
label={i18n("english_suggest")}
|
||||
onChange={(e) => {
|
||||
setEnSug(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={"-"}>{i18n("disable")}</MenuItem>
|
||||
{OPT_SUG_ALL.map((item) => (
|
||||
<MenuItem value={item} key={item}>
|
||||
{item}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{
|
||||
MenuProps: { disablePortal: !isPlaygound },
|
||||
}}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="langDetector"
|
||||
value={langDetector}
|
||||
label={i18n("detected_lang")}
|
||||
onChange={(e) => {
|
||||
setLangDetector(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={"-"}>{i18n("disable")}</MenuItem>
|
||||
{OPT_LANGDETECTOR_ALL.map((item) => (
|
||||
<MenuItem value={item} key={item}>
|
||||
{item}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={xs}>
|
||||
<TextField
|
||||
fullWidth
|
||||
size="small"
|
||||
name="deLang"
|
||||
value={deLang && OPT_LANGS_MAP.get(deLang)}
|
||||
label={i18n("detected_result")}
|
||||
disabled
|
||||
InputProps={{
|
||||
startAdornment: deLoading ? (
|
||||
<CircularProgress size={16} />
|
||||
) : null,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
{isPlaygound && (
|
||||
<Box>
|
||||
<Grid container spacing={2} columns={12}>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="enDict"
|
||||
value={enDict}
|
||||
label={i18n("english_dict")}
|
||||
onChange={(e) => {
|
||||
setEnDict(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={"-"}>{i18n("disable")}</MenuItem>
|
||||
{OPT_DICT_ALL.map((item) => (
|
||||
<MenuItem value={item} key={item}>
|
||||
{item}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="langDetector"
|
||||
value={langDetector}
|
||||
label={i18n("detected_lang")}
|
||||
onChange={(e) => {
|
||||
setLangDetector(e.target.value);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={"-"}>{i18n("disable")}</MenuItem>
|
||||
{OPT_LANGDETECTOR_ALL.map((item) => (
|
||||
<MenuItem value={item} key={item}>
|
||||
{item}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<TextField
|
||||
fullWidth
|
||||
size="small"
|
||||
name="deLang"
|
||||
value={deLang && OPT_LANGS_MAP.get(deLang)}
|
||||
label={i18n("detected_result")}
|
||||
disabled
|
||||
InputProps={{
|
||||
startAdornment: deLoading ? (
|
||||
<CircularProgress size={16} />
|
||||
) : null,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box>
|
||||
<TextField
|
||||
size="small"
|
||||
@@ -267,6 +326,8 @@ export default function TranForm({
|
||||
size="small"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setEditMode(false);
|
||||
setText(editText.trim());
|
||||
}}
|
||||
>
|
||||
<DoneIcon fontSize="inherit" />
|
||||
@@ -295,10 +356,11 @@ export default function TranForm({
|
||||
))}
|
||||
|
||||
{isWord && OPT_DICT_MAP.has(enDict) && (
|
||||
<>
|
||||
<DictCont text={text} enDict={enDict} />
|
||||
<SugCont text={text} />
|
||||
</>
|
||||
<DictCont text={text} enDict={enDict} />
|
||||
)}
|
||||
|
||||
{isWord && OPT_SUG_MAP.has(enSug) && (
|
||||
<SugCont text={text} enSug={enSug} />
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
OPT_TRANBOX_TRIGGER_CLICK,
|
||||
OPT_TRANBOX_TRIGGER_HOVER,
|
||||
OPT_TRANBOX_TRIGGER_SELECT,
|
||||
OPT_DICT_BAIDU,
|
||||
} from "../../config";
|
||||
import { isMobile } from "../../libs/mobile";
|
||||
import { kissLog } from "../../libs/log";
|
||||
@@ -35,7 +34,6 @@ export default function Slection({
|
||||
btnOffsetY,
|
||||
boxOffsetX = 0,
|
||||
boxOffsetY = 10,
|
||||
enDict = OPT_DICT_BAIDU,
|
||||
} = tranboxSetting;
|
||||
|
||||
const boxWidth =
|
||||
@@ -238,7 +236,6 @@ export default function Slection({
|
||||
setFollowSelection={setFollowSelection}
|
||||
// extStyles={extStyles}
|
||||
langDetector={langDetector}
|
||||
enDict={enDict}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user