diff --git a/enjoy/src/constants/dicts.ts b/enjoy/src/constants/dicts.ts
index f55a686b..b6133d6d 100644
--- a/enjoy/src/constants/dicts.ts
+++ b/enjoy/src/constants/dicts.ts
@@ -8,6 +8,7 @@ export const DICTS = [
downloadUrl: "https://dl.enjoy.bot/dicts/ccalecd.zip",
size: "13.879MB",
hash: "96940f85e52df4586b287e1859723a39",
+ sqlFileHash: "e1e7baafaa8bce936409763d27a027f8",
addition: '',
},
@@ -20,6 +21,7 @@ export const DICTS = [
downloadUrl: "https://dl.enjoy.bot/dicts/ccabeld.zip",
size: "485.6MB",
hash: "5b53498536f3ce3ed173752b7888ca51",
+ sqlFileHash: "0eed5c046a006f3fe0c7a4af1bee5da1",
addition: '',
},
{
@@ -31,6 +33,7 @@ export const DICTS = [
downloadUrl: "https://dl.enjoy.bot/dicts/ldoce5.zip",
size: "1.63GB",
hash: "4a03ce291ea7b6e0ea46f4c2fc335ad4",
+ sqlFileHash: "b38a9e55bd97c5acfa267b87c825baf7",
addition: '',
},
{
@@ -41,6 +44,7 @@ export const DICTS = [
lang: "En-En",
downloadUrl: "https://dl.enjoy.bot/dicts/oxford_en_mac.zip",
hash: "cffaef4b3ed6ec7d3ee7209b18e05c6f",
+ sqlFileHash: "3362137bf8e2e2578665db3ad8d49814",
size: "33.6MB",
addition: '',
},
@@ -53,6 +57,7 @@ export const DICTS = [
downloadUrl: "https://dl.enjoy.bot/dicts/koen_mac.zip",
size: "52.1MB",
hash: "fa028c585de10e54a7028c6683738499",
+ sqlFileHash: "e55f771e6acd50d757428fe61f13650e",
addition: '',
},
{
@@ -63,6 +68,7 @@ export const DICTS = [
lang: "Ja-En",
downloadUrl: "https://dl.enjoy.bot/dicts/jaen_mac.zip",
hash: "3008e1cd2a8b6f224f90d14a8e1de9cb",
+ sqlFileHash: "76597b8608ba085b9b88adce10449bf3",
size: "39.8MB",
addition: '',
},
@@ -74,6 +80,7 @@ export const DICTS = [
lang: "Ge-En",
downloadUrl: "https://dl.enjoy.bot/dicts/deen_mac.zip",
hash: "3fedde07108236f6e6cfe907bd60faba",
+ sqlFileHash: "84b3097bfa83cdae8c264ca595923101",
size: "32.1MB",
addition: '',
},
@@ -85,6 +92,7 @@ export const DICTS = [
lang: "Ru-En",
downloadUrl: "https://dl.enjoy.bot/dicts/ruen_mac.zip",
hash: "5b98fc0e5c3de9df43189cb79d5bf4cc",
+ sqlFileHash: "1d72eadd51d82d48b3c772e5580d3524",
size: "18.1MB",
addition: '',
},
diff --git a/enjoy/src/i18n/en.json b/enjoy/src/i18n/en.json
index 9a89cbb3..12dfa491 100644
--- a/enjoy/src/i18n/en.json
+++ b/enjoy/src/i18n/en.json
@@ -744,7 +744,7 @@
"recorderConfig": "Recorder config",
"recorderConfigSaved": "Recorder config saved",
"recorderConfigDescription": "Advanced settings for recorder",
- "lookupOnMouseOver": "Lookup On MouseOver",
+ "lookupOnMouseOver": "Lookup On Click",
"selectDictFile": "Select Dict Files (extension with .mdx and .mdd files)",
"dictFiles": "Dict Files",
"dictFileRequired": "Dict file (the extension is mdx) not found.",
@@ -771,5 +771,14 @@
"removeDictTitle": "Are you sure you want to delete this dictionary? ",
"removeDictDescription": "It will delete the dictionary file from your local computer and you will have to download it again next time.",
"downloadingDict": "Downloading",
- "removeDefault": "No longer as Default"
+ "removeDefault": "No longer as Default",
+ "selectAdaptionDictTitle": "Select adapted dictionary folder",
+ "selectMdictFileOrDirTitle": "Select dict files (.mdx and optional .mdd) or folder",
+ "dictImportSlowTip": "It may take longer if the dictionary file is large.",
+ "importAdaptionDict": "Import the adapted dictionary",
+ "adaptionDictTip": "The adapted dictionaries have better usability.",
+ "howToDownload": "How to download?",
+ "selectDir": "Select Folder",
+ "importMdictFile": "Import the original dictionary file",
+ "mdictFileTip": "Directly import .mdx .mdd format files (.mdx files are required, .mdd files are optional and can have multiple), but there may be problems with style and usability."
}
diff --git a/enjoy/src/i18n/zh-CN.json b/enjoy/src/i18n/zh-CN.json
index a51cc072..5af46464 100644
--- a/enjoy/src/i18n/zh-CN.json
+++ b/enjoy/src/i18n/zh-CN.json
@@ -744,7 +744,7 @@
"recorderConfig": "录音设置",
"recorderConfigSaved": "录音设置已保存",
"recorderConfigDescription": "调整录音高级设置",
- "lookupOnMouseOver": "鼠标悬停查询单词",
+ "lookupOnMouseOver": "鼠标点击查询单词",
"selectDictFile": "选择字典文件 (扩展名为 .mdx 和 .mdd 的文件)",
"dictFiles": "字典文件",
"dictFileRequired": "未找到字典文件 (扩展名为 .mdx 的文件是必须的) ",
@@ -771,5 +771,14 @@
"removeDictTitle": "你确定要删除词典吗?",
"removeDictDescription": "此操作将会从本地删除词典文件,下次安装需要重新下载",
"downloadingDict": "正在下载",
- "removeDefault": "不再设置为默认"
+ "removeDefault": "不再设置为默认",
+ "selectAdaptionDictTitle": "选择预先适配的词典文件夹",
+ "selectMdictFileOrDirTitle": "选择词典文件 (.mdx 和可选的 .mdd 文件) or 文件夹",
+ "dictImportSlowTip": "词典文件较大时可能需要的时间比较长",
+ "importAdaptionDict": "导入已经适配好的词典",
+ "adaptionDictTip": "已经适配好的词典可用性较好。",
+ "howToDownload": "如何下载?",
+ "selectDir": "选择文件夹",
+ "importMdictFile": "导入原词典文件",
+ "mdictFileTip": "直接导入 .mdx .mdd 格式的文件 (.mdx 文件是必须的,.mdd 文件是可选的且可以有多个),不过样式和可用性可能存在问题。"
}
diff --git a/enjoy/src/index.css b/enjoy/src/index.css
index f8e1396a..88aca05f 100644
--- a/enjoy/src/index.css
+++ b/enjoy/src/index.css
@@ -37,6 +37,7 @@
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 10% 3.9%;
+ --active-word: 201 94% 86%;
--radius: 0.5rem;
}
@@ -69,6 +70,7 @@
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
+ --active-word: 201 93% 30%;
}
}
diff --git a/enjoy/src/main/dict.ts b/enjoy/src/main/dict.ts
index 24578a54..a120732c 100644
--- a/enjoy/src/main/dict.ts
+++ b/enjoy/src/main/dict.ts
@@ -6,8 +6,6 @@ import log from "@main/logger";
import { DICTS } from "@/constants/dicts";
import sqlite3, { Database } from "sqlite3";
import settings from "./settings";
-import downloader from "./downloader";
-import decompresser from "./decompresser";
import { hashFile } from "@/main/utils";
const logger = log.scope("dict");
@@ -25,54 +23,28 @@ export class DictHandler {
return _path;
}
- async isDictFileValid(dict: Dict) {
- const filePath = path.join(this.dictsPath, dict.fileName);
+ async import(dir: string) {
+ const files = await fs.readdir(dir);
- if (!fs.existsSync(filePath)) return false;
-
- const hash = await hashFile(filePath, { algo: "md5" });
-
- return hash === dict.hash;
- }
-
- async download(dict: Dict) {
- const filePath = path.join(this.dictsPath, dict.fileName);
- const dictPath = path.join(this.dictsPath, dict.name);
-
- if (fs.existsSync(dictPath)) {
- throw new Error("Dictionary already exists");
+ const sqlFileName = files.find((file) => file.match(/\.sqlite$/));
+ if (!sqlFileName) {
+ throw new Error("SQLite file not found");
}
- const isDictFileValid = await this.isDictFileValid(dict);
-
- if (isDictFileValid) {
- this.decompress(dict);
- } else {
- if (fs.existsSync(filePath)) {
- await fs.remove(filePath);
- }
-
- downloader.download(dict.downloadUrl, {
- savePath: this.dictsPath,
- });
- }
- }
-
- async decompress(dict: Dict) {
- const filePath = path.join(this.dictsPath, dict.fileName);
- const dictPath = path.join(this.dictsPath, dict.name);
- const isDictFileValid = await this.isDictFileValid(dict);
-
- if (isDictFileValid) {
- await decompresser.depress({
- filePath,
- hash: dict.hash,
- destPath: dictPath,
- id: `dict-${dict.fileName}`,
- });
+ const sqlFilePath = path.join(dir, sqlFileName);
+ const hash = await hashFile(sqlFilePath, { algo: "md5" });
+ const dict = DICTS.find((dict) => dict.sqlFileHash === hash);
+ if (!dict) {
+ throw new Error("SQLite file not match with any perset dictionary");
}
- downloader.remove(dict.fileName);
+ if (this.isInstalled(dict)) {
+ throw new Error("Current dict is already installed");
+ }
+
+ await fs.copy(dir, path.join(this.dictsPath, dict.name), {
+ recursive: true,
+ });
}
async remove(dict: Dict) {
@@ -84,6 +56,7 @@ export class DictHandler {
this.db = new sqlite.Database(
path.join(this.dictsPath, dict.name, `${dict.name}.sqlite`)
);
+
this.currentDict = dict.name;
}
@@ -104,41 +77,17 @@ export class DictHandler {
});
}
+ isInstalled(dict: Dict) {
+ const files = fs.readdirSync(this.dictsPath);
+ return files.find((file) => file === dict.name);
+ }
+
async getDicts() {
const dicts = DICTS.map((dict: Dict) => {
- let state: DictState = "uninstall";
- let downloadState;
- let decompressProgress;
-
- const files = fs.readdirSync(this.dictsPath);
- const isInstalled = files.find((file) => file === dict.name);
-
- const decompressTask = decompresser.tasks.find(
- (task) => task.id === `dict-${dict.fileName}`
- );
-
- const downloadTask = downloader.tasks.find(
- (task) => task.getFilename() === dict.fileName
- );
-
- if (decompressTask) {
- state = "decompressing";
- decompressProgress = decompressTask.progress;
- } else if (isInstalled) {
- state = "installed";
- } else if (downloadTask) {
- state = "downloading";
- downloadState = {
- name: downloadTask.getFilename(),
- state: downloadTask.getState(),
- isPaused: downloadTask.isPaused(),
- canResume: downloadTask.canResume(),
- total: downloadTask.getTotalBytes(),
- received: downloadTask.getReceivedBytes(),
- };
- }
-
- return { ...dict, state, downloadState, decompressProgress };
+ return {
+ ...dict,
+ state: this.isInstalled(dict) ? "installed" : "uninstall",
+ };
});
return dicts;
@@ -161,12 +110,8 @@ export class DictHandler {
}
registerIpcHandlers() {
- ipcMain.handle("dict-download", async (_event, dict: Dict) =>
- this.download(dict)
- );
-
- ipcMain.handle("dict-decompress", async (_event, dict: Dict) =>
- this.decompress(dict)
+ ipcMain.handle("dict-import", async (_event, dir: string) =>
+ this.import(dir)
);
ipcMain.handle("dict-remove", async (_event, dict: Dict) =>
diff --git a/enjoy/src/preload.ts b/enjoy/src/preload.ts
index 017241b8..9f7a8384 100644
--- a/enjoy/src/preload.ts
+++ b/enjoy/src/preload.ts
@@ -281,13 +281,12 @@ contextBridge.exposeInMainWorld("__ENJOY_APP__", {
},
dict: {
getDicts: () => ipcRenderer.invoke("dict-list"),
- download: (dict: Dict) => ipcRenderer.invoke("dict-download", dict),
- decompress: (dict: Dict) => ipcRenderer.invoke("dict-decompress", dict),
remove: (dict: Dict) => ipcRenderer.invoke("dict-remove", dict),
getResource: (key: string, dict: Dict) =>
ipcRenderer.invoke("dict-read-file", key, dict),
lookup: (word: string, dict: Dict) =>
ipcRenderer.invoke("dict-lookup", word, dict),
+ import: (path: string) => ipcRenderer.invoke("dict-import", path),
},
audios: {
findAll: (params: {
diff --git a/enjoy/src/renderer.ts b/enjoy/src/renderer.ts
index f3c7ec81..3b6239b8 100644
--- a/enjoy/src/renderer.ts
+++ b/enjoy/src/renderer.ts
@@ -33,4 +33,10 @@ declare global {
interface Window {
__ENJOY_APP__: EnjoyAppType;
}
+
+ namespace JSX {
+ interface IntrinsicElements {
+ vocabulary: any;
+ }
+ }
}
diff --git a/enjoy/src/renderer/components/meanings/meaning-memorizing-card.tsx b/enjoy/src/renderer/components/meanings/meaning-memorizing-card.tsx
index 4838a187..2a0420b4 100644
--- a/enjoy/src/renderer/components/meanings/meaning-memorizing-card.tsx
+++ b/enjoy/src/renderer/components/meanings/meaning-memorizing-card.tsx
@@ -4,6 +4,7 @@ import { Button, ScrollArea, Separator } from "@renderer/components/ui";
import Mark from "mark.js";
import { useHotkeys } from "react-hotkeys-hook";
import { HotKeysSettingsProviderContext } from "@renderer/context";
+import { Sentence } from "@renderer/components";
export const MeaningMemorizingCard = (props: { meaning: MeaningType }) => {
const {
@@ -73,7 +74,7 @@ const FrontSide = (props: {
{lookups.map((lookup) => (
- {lookup.context}
+
))}
@@ -159,8 +160,10 @@ const BackSide = (props: { meaning: MeaningType; onFlip: () => void }) => {
{lookups.map((lookup) => (
-
{lookup.context}
-
{lookup.contextTranslation}
+
+
+ {lookup.contextTranslation}
+
))}
diff --git a/enjoy/src/renderer/components/medias/media-caption.tsx b/enjoy/src/renderer/components/medias/media-caption.tsx
index 644796b9..26b3d9c3 100644
--- a/enjoy/src/renderer/components/medias/media-caption.tsx
+++ b/enjoy/src/renderer/components/medias/media-caption.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useState, useContext } from "react";
+import { useEffect, useState, useContext, useRef } from "react";
import {
AppSettingsProviderContext,
MediaPlayerProviderContext,
@@ -51,6 +51,7 @@ export const MediaCaption = () => {
const [copied, setCopied] = useState(false);
const [caption, setCaption] = useState(null);
+ const [tab, setTab] = useState("translation");
const toggleMultiSelect = (event: KeyboardEvent) => {
setMultiSelecting(event.shiftKey && event.type === "keydown");
@@ -362,12 +363,15 @@ export const MediaCaption = () => {
{
export const Caption = (props: {
caption: TimelineEntry;
+ tab: string;
language?: string;
selectedIndices?: number[];
currentSegmentIndex: number;
@@ -544,7 +549,7 @@ export const Caption = (props: {
}`}
onClick={() => onClick && onClick(index)}
>
-
+ {word}
{displayIpa && (
diff --git a/enjoy/src/renderer/components/medias/media-captions/media-caption-tabs.tsx b/enjoy/src/renderer/components/medias/media-captions/media-caption-tabs.tsx
index 6436cd17..6137521f 100644
--- a/enjoy/src/renderer/components/medias/media-captions/media-caption-tabs.tsx
+++ b/enjoy/src/renderer/components/medias/media-captions/media-caption-tabs.tsx
@@ -13,8 +13,10 @@ import { TabContentNote } from "./tab-content-note";
export const MediaCaptionTabs = (props: {
caption: TimelineEntry;
+ tab: string;
currentSegmentIndex: number;
selectedIndices: number[];
+ setTab: (v: string) => void;
setSelectedIndices: (indices: number[]) => void;
children?: React.ReactNode;
}) => {
@@ -24,10 +26,10 @@ export const MediaCaptionTabs = (props: {
selectedIndices,
setSelectedIndices,
children,
+ tab,
+ setTab,
} = props;
- const [tab, setTab] = useState
("translation");
-
if (!caption) return null;
return (
diff --git a/enjoy/src/renderer/components/medias/media-transcription.tsx b/enjoy/src/renderer/components/medias/media-transcription.tsx
index 49443a7e..d0b1e689 100644
--- a/enjoy/src/renderer/components/medias/media-transcription.tsx
+++ b/enjoy/src/renderer/components/medias/media-transcription.tsx
@@ -29,6 +29,7 @@ import {
MediaTranscriptionPrint,
TranscriptionEditButton,
} from "@renderer/components";
+import { Sentence } from "@renderer/components";
export const MediaTranscription = (props: { display?: boolean }) => {
const { display } = props;
@@ -202,7 +203,8 @@ export const MediaTranscription = (props: { display?: boolean }) => {
- {sentence.text}
+
+
)
)}
diff --git a/enjoy/src/renderer/components/misc/markdown-wrapper.tsx b/enjoy/src/renderer/components/misc/markdown-wrapper.tsx
index 04135588..5339ecb0 100644
--- a/enjoy/src/renderer/components/misc/markdown-wrapper.tsx
+++ b/enjoy/src/renderer/components/misc/markdown-wrapper.tsx
@@ -1,4 +1,21 @@
import Markdown from "react-markdown";
+import { visitParents } from "unist-util-visit-parents";
+import { Sentence } from "@renderer/components";
+
+function rehypeWrapText() {
+ return function wrapTextTransform(tree: any) {
+ visitParents(tree, "text", (node, ancestors) => {
+ const parent = ancestors.at(-1);
+
+ if (parent.tagName !== "vocabulary") {
+ node.type = "element";
+ node.tagName = "vocabulary";
+ node.properties = { text: node.value };
+ node.children = [{ type: "text", value: node.value }];
+ }
+ });
+ };
+}
export const MarkdownWrapper = ({
children,
@@ -11,6 +28,7 @@ export const MarkdownWrapper = ({
return (
{children};
},
+ vocabulary({ node, children, ...props }) {
+ return ;
+ },
}}
{...props}
>
diff --git a/enjoy/src/renderer/components/notes/note-segment.tsx b/enjoy/src/renderer/components/notes/note-segment.tsx
index f2f1eb9d..854eafea 100644
--- a/enjoy/src/renderer/components/notes/note-segment.tsx
+++ b/enjoy/src/renderer/components/notes/note-segment.tsx
@@ -3,6 +3,7 @@ import { useContext, useState } from "react";
import { WavesurferPlayer } from "@/renderer/components/misc";
import { AppSettingsProviderContext } from "@/renderer/context";
import { convertWordIpaToNormal } from "@/utils";
+import { Vocabulary } from "@renderer/components";
export const NoteSemgent = (props: {
segment: SegmentType;
@@ -51,7 +52,7 @@ export const NoteSemgent = (props: {
}
`}
>
- {word}
+
- {recording.referenceText}
+
)}
diff --git a/enjoy/src/renderer/components/preferences/dict-settings/dict-import-button.tsx b/enjoy/src/renderer/components/preferences/dict-settings/dict-import-button.tsx
index 1a10591b..448a9421 100644
--- a/enjoy/src/renderer/components/preferences/dict-settings/dict-import-button.tsx
+++ b/enjoy/src/renderer/components/preferences/dict-settings/dict-import-button.tsx
@@ -1,4 +1,8 @@
-import { useState } from "react";
+import { useState, useContext } from "react";
+import {
+ AppSettingsProviderContext,
+ DictProviderContext,
+} from "@/renderer/context";
import {
Button,
Dialog,
@@ -6,20 +10,54 @@ import {
DialogContent,
DialogHeader,
DialogTitle,
- ScrollArea,
+ toast,
} from "@/renderer/components/ui";
-import { UninstallDictList } from ".";
import { t } from "i18next";
+import { LoaderIcon } from "lucide-react";
export const DictImportButton = () => {
+ const { reload } = useContext(DictProviderContext);
+ const { EnjoyApp } = useContext(AppSettingsProviderContext);
const [open, setOpen] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [tipVisible, setTipVisible] = useState(false);
const handleOpen = (value: boolean) => {
setOpen(value);
};
- const handleDownload = () => {
- setOpen(false);
+ const handleAdaptationDictImport = async () => {
+ const pathes = await EnjoyApp.dialog.showOpenDialog({
+ title: t("selectAdaptionDictTitle"),
+ properties: ["openDirectory"],
+ });
+
+ if (!pathes[0]) return;
+
+ setLoading(true);
+ setTimeout(() => {
+ if (loading) {
+ setTipVisible(true);
+ }
+ }, 10000);
+
+ try {
+ await EnjoyApp.dict.import(pathes[0]);
+ setOpen(false);
+ } catch (err) {
+ toast.error(err.message);
+ }
+
+ setLoading(false);
+ setTipVisible(false);
+ reload();
+ };
+
+ const handleOriginDictImport = async () => {
+ const pathes = await EnjoyApp.dialog.showOpenDialog({
+ title: t("selectMdictFileOrDirTitle"),
+ properties: ["multiSelections", "openFile", "openDirectory"],
+ });
};
return (
@@ -32,9 +70,56 @@ export const DictImportButton = () => {
{t("importDict")}
-
-
-
+ {loading ? (
+
+
+
+
+ {tipVisible && (
+
+ {t("dictImportSlowTip")}
+
+ )}
+
+ ) : (
+
+
+
+
{t("importAdaptionDict")}
+
+
+
+
+
+
+ {/*
+
+
{t("importMdictFile")}
+
+ {t("mdictFileTip")}
+
+
+
+
+
*/}
+
+ )}
);
diff --git a/enjoy/src/renderer/components/preferences/dict-settings/dict-settings.tsx b/enjoy/src/renderer/components/preferences/dict-settings/dict-settings.tsx
index 519b84c8..37c84c99 100644
--- a/enjoy/src/renderer/components/preferences/dict-settings/dict-settings.tsx
+++ b/enjoy/src/renderer/components/preferences/dict-settings/dict-settings.tsx
@@ -1,6 +1,6 @@
import { t } from "i18next";
import { DictImportButton } from "./dict-import-button";
-import { DownloadingDictList, InstalledDictList } from ".";
+import { InstalledDictList } from ".";
export const DictSettings = () => {
return (
@@ -12,7 +12,6 @@ export const DictSettings = () => {
-
diff --git a/enjoy/src/renderer/components/preferences/dict-settings/downloading-dict-list.tsx b/enjoy/src/renderer/components/preferences/dict-settings/downloading-dict-list.tsx
deleted file mode 100644
index 767b41c7..00000000
--- a/enjoy/src/renderer/components/preferences/dict-settings/downloading-dict-list.tsx
+++ /dev/null
@@ -1,189 +0,0 @@
-import {
- DictProviderContext,
- AppSettingsProviderContext,
-} from "@/renderer/context";
-import { useContext, useEffect, useState } from "react";
-import { Button, toast } from "@renderer/components/ui";
-import { t } from "i18next";
-import { LoaderIcon } from "lucide-react";
-
-export const DownloadingDictList = function () {
- const { EnjoyApp } = useContext(AppSettingsProviderContext);
- const { downloadingDicts, reload } = useContext(DictProviderContext);
-
- useEffect(() => {
- listenToDownloadState();
- listenDecompressState();
-
- return () => {
- EnjoyApp.download.removeAllListeners();
- EnjoyApp.decompress.removeAllListeners();
- };
- }, []);
-
- const listenToDownloadState = () => {
- EnjoyApp.download.onState((_event, state) => {
- reload();
- });
- };
-
- const listenDecompressState = () => {
- EnjoyApp.decompress.onUpdate((_event, tasks) => {
- reload();
- });
- };
-
- return (
- <>
- {downloadingDicts.map((item) => (
-
- ))}
- >
- );
-};
-
-const DownloadingDictItem = function ({ dict }: { dict: Dict }) {
- const { EnjoyApp } = useContext(AppSettingsProviderContext);
- const { reload } = useContext(DictProviderContext);
- const [loading, setLoading] = useState(false);
-
- useEffect(() => {
- if (dict.downloadState?.state === "completed") {
- EnjoyApp.dict.decompress(dict);
- }
- }, [dict]);
-
- async function handlePause() {
- setLoading(true);
-
- try {
- await EnjoyApp.download.pause(dict.downloadState.name);
- reload();
- } catch (err) {
- toast.error(err.message);
- }
-
- setLoading(false);
- }
-
- async function handleResume() {
- setLoading(true);
-
- try {
- await EnjoyApp.download.resume(dict.downloadState.name);
- reload();
- } catch (err) {
- toast.error(err.message);
- }
-
- setLoading(false);
- }
-
- async function handleRemove() {
- setLoading(true);
-
- try {
- await EnjoyApp.download.remove(dict.downloadState.name);
- toast.success(t("dictRemoved"));
- reload();
- } catch (err) {
- toast.error(err.message);
- }
-
- setLoading(false);
- }
-
- function displaySize(bytes: number) {
- return Number((bytes / 1024 / 1024).toFixed(0)).toLocaleString() + "MB";
- }
-
- function renderDownloadState() {
- const text =
- dict.downloadState.state === "cancelled"
- ? t("cancelled")
- : dict.downloadState.state === "completed"
- ? t("completedAndChecking")
- : dict.downloadState.state === "interrupted"
- ? t("interrupted")
- : dict.downloadState.isPaused
- ? t("paused")
- : t("downloadingDict");
-
- return (
-
- {text}
- {displaySize(dict.downloadState.received)}
- /
- {displaySize(dict.downloadState.total)}
-
- );
- }
-
- function renderDecompressState() {
- return (
-
- {t("decompressing")}
- {dict.decompressProgress ?? "0"}%
-
- );
- }
-
- function renderActions() {
- if (loading)
- return (
-
-
-
- );
-
- if (
- dict.downloadState?.state === "progressing" &&
- !dict.downloadState?.isPaused
- ) {
- return (
-
- );
- }
-
- if (
- dict.downloadState?.state === "cancelled" ||
- dict.downloadState?.state === "interrupted" ||
- (dict.downloadState?.state === "progressing" &&
- dict.downloadState?.isPaused)
- ) {
- return (
- <>
- {dict.downloadState.canResume && (
-
- )}
-
-
- >
- );
- }
- }
-
- return (
-
-
-
{dict.title}
-
- {dict.state === "decompressing" && renderDecompressState()}
- {dict.downloadState && renderDownloadState()}
-
-
- {renderActions()}
-
- );
-};
diff --git a/enjoy/src/renderer/components/preferences/dict-settings/index.ts b/enjoy/src/renderer/components/preferences/dict-settings/index.ts
index 498272e7..4b22593c 100644
--- a/enjoy/src/renderer/components/preferences/dict-settings/index.ts
+++ b/enjoy/src/renderer/components/preferences/dict-settings/index.ts
@@ -1,5 +1,3 @@
export * from "./dict-settings";
export * from "./dict-import-button";
-export * from "./downloading-dict-list";
export * from "./installed-dict-list";
-export * from "./uninstall-dict-list";
diff --git a/enjoy/src/renderer/components/preferences/dict-settings/installed-dict-list.tsx b/enjoy/src/renderer/components/preferences/dict-settings/installed-dict-list.tsx
index 8ee55dc3..e5484950 100644
--- a/enjoy/src/renderer/components/preferences/dict-settings/installed-dict-list.tsx
+++ b/enjoy/src/renderer/components/preferences/dict-settings/installed-dict-list.tsx
@@ -19,14 +19,13 @@ import {
import { t } from "i18next";
export const InstalledDictList = function () {
- const { installedDicts, downloadingDicts, reload } =
- useContext(DictProviderContext);
+ const { installedDicts, reload } = useContext(DictProviderContext);
useEffect(() => {
reload();
}, []);
- if (installedDicts.length === 0 && downloadingDicts.length === 0) {
+ if (installedDicts.length === 0) {
return (
{t("dictEmpty")}
);
@@ -119,6 +118,7 @@ const InstalledDictItem = function ({ dict }: { dict: Dict }) {