Files
kiss-translator/src/views/Options/FavWords.js
2025-10-04 22:29:03 +08:00

156 lines
4.4 KiB
JavaScript

import Stack from "@mui/material/Stack";
import { useState } from "react";
import Typography from "@mui/material/Typography";
import Accordion from "@mui/material/Accordion";
import AccordionSummary from "@mui/material/AccordionSummary";
import AccordionDetails from "@mui/material/AccordionDetails";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { useI18n } from "../../hooks/I18n";
import Box from "@mui/material/Box";
import { useFavWords } from "../../hooks/FavWords";
import DictCont from "../Selection/DictCont";
import SugCont from "../Selection/SugCont";
import DownloadButton from "./DownloadButton";
import UploadButton from "./UploadButton";
import Button from "@mui/material/Button";
import ClearAllIcon from "@mui/icons-material/ClearAll";
import Alert from "@mui/material/Alert";
import { isValidWord } from "../../libs/utils";
import { kissLog } from "../../libs/log";
import { useConfirm } from "../../hooks/Confirm";
import { useSetting } from "../../hooks/Setting";
import { dictHandlers } from "../Selection/DictHandler";
function FavAccordion({ word, index }) {
const [expanded, setExpanded] = useState(false);
const { setting } = useSetting();
const { enDict, enSug } = setting?.tranboxSetting || {};
const handleChange = (e) => {
setExpanded((pre) => !pre);
};
return (
<Accordion expanded={expanded} onChange={handleChange}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
{/* <Typography>{`[${new Date(
createdAt
).toLocaleString()}] ${word}`}</Typography> */}
<Typography>{`${index + 1}. ${word}`}</Typography>
</AccordionSummary>
<AccordionDetails>
{expanded && (
<Stack spacing={2}>
<DictCont text={word} enDict={enDict} />
<SugCont text={word} enSug={enSug} />
</Stack>
)}
</AccordionDetails>
</Accordion>
);
}
export default function FavWords() {
const i18n = useI18n();
const { favList, wordList, mergeWords, clearWords } = useFavWords();
const { setting } = useSetting();
const confirm = useConfirm();
const handleImport = (data) => {
try {
const newWords = data
.split("\n")
.map((line) => line.split(",")[0].trim())
.filter(isValidWord);
mergeWords(newWords);
} catch (err) {
kissLog("import rules", err);
}
};
const handleClearWords = async () => {
const isConfirmed = await confirm({
confirmText: i18n("confirm_title"),
cancelText: i18n("cancel"),
});
if (isConfirmed) {
clearWords();
}
};
const handleTranslation = async () => {
const { enDict } = setting?.tranboxSetting;
const dict = dictHandlers[enDict];
if (!dict) return "";
const tranList = [];
for (const word of wordList) {
try {
const data = await dict.apiFn(word);
const title = `## ${dict.reWord(data) || word}`;
const tran = dict
.toText(data)
.map((line) => `- ${line}`)
.join("\n");
tranList.push([title, tran].join("\n"));
} catch (err) {
kissLog("export translation", err);
}
}
return tranList.join("\n\n");
};
return (
<Box>
<Stack spacing={3}>
<Alert severity="info">{i18n("favorite_words_helper")}</Alert>
<Stack
direction="row"
alignItems="center"
spacing={2}
useFlexGap
flexWrap="wrap"
>
<UploadButton
text={i18n("import")}
handleImport={handleImport}
fileType="text"
fileExts={[".txt", ".csv"]}
/>
<DownloadButton
handleData={() => wordList.join("\n")}
text={i18n("export")}
fileName={`kiss-words_${Date.now()}.txt`}
/>
<DownloadButton
handleData={handleTranslation}
text={i18n("export_translation")}
fileName={`kiss-words_${Date.now()}.md`}
/>
<Button
size="small"
variant="outlined"
onClick={handleClearWords}
startIcon={<ClearAllIcon />}
>
{i18n("clear_all")}
</Button>
</Stack>
<Box>
{favList.map(([word, { createdAt }], index) => (
<FavAccordion
key={word}
index={index}
word={word}
createdAt={createdAt}
/>
))}
</Box>
</Stack>
</Box>
);
}