From 89faf354833bb7b0ea911a20ec81f8c0b4720b18 Mon Sep 17 00:00:00 2001 From: an-lee Date: Wed, 15 May 2024 17:06:10 +0800 Subject: [PATCH] refactor ai lookup --- enjoy/src/commands/lookup.command.ts | 3 +- enjoy/src/i18n/en.json | 3 +- enjoy/src/i18n/zh-CN.json | 1 + .../components/widgets/lookup-widget.tsx | 105 ++++++++++++------ enjoy/src/renderer/hooks/use-ai-command.tsx | 31 +++--- 5 files changed, 91 insertions(+), 52 deletions(-) diff --git a/enjoy/src/commands/lookup.command.ts b/enjoy/src/commands/lookup.command.ts index 364095ced..6564a734c 100644 --- a/enjoy/src/commands/lookup.command.ts +++ b/enjoy/src/commands/lookup.command.ts @@ -57,9 +57,8 @@ const DICITIONARY_PROMPT = `You are an {learning_language}-{native_language} dic I will provide "word(it also maybe a phrase)" and "context" as input, you should return the "word", "lemma", "pronunciation", "pos", "definition", "translation" and "context_translation" as output. If no context is provided, return the most common definition. If you do not know the appropriate definition, return an empty string for "definition" and "translation". -Always return output in JSON format. +Always return the output in JSON format as following: -The output format: {{ "word": "the original word or phrase", "lemma": "lemma", diff --git a/enjoy/src/i18n/en.json b/enjoy/src/i18n/en.json index ad2717607..ffd94a798 100644 --- a/enjoy/src/i18n/en.json +++ b/enjoy/src/i18n/en.json @@ -436,7 +436,8 @@ "extracting": "Extracting", "extractionFailed": "Extraction failed", "extractedSuccessfully": "Extracted successfully", - "lookup": "Look up", + "lookup": "Lookup", + "reLookup": "Re-Lookup", "lookupAll": "Look up all", "lookingUp": "Looking up", "pending": "Pending", diff --git a/enjoy/src/i18n/zh-CN.json b/enjoy/src/i18n/zh-CN.json index 97829d6af..2ee81f194 100644 --- a/enjoy/src/i18n/zh-CN.json +++ b/enjoy/src/i18n/zh-CN.json @@ -437,6 +437,7 @@ "extractionFailed": "提取失败", "extractedSuccessfully": "提取成功", "lookup": "查询", + "reLookup": "重新查询", "lookupAll": "全部查询", "lookingUp": "正在查询", "pending": "等待中", diff --git a/enjoy/src/renderer/components/widgets/lookup-widget.tsx b/enjoy/src/renderer/components/widgets/lookup-widget.tsx index 3b7dc8843..38cf48c38 100644 --- a/enjoy/src/renderer/components/widgets/lookup-widget.tsx +++ b/enjoy/src/renderer/components/widgets/lookup-widget.tsx @@ -12,6 +12,7 @@ import { import { useAiCommand, useCamdict } from "@renderer/hooks"; import { LoaderIcon, Volume2Icon } from "lucide-react"; import { t } from "i18next"; +import { md5 } from "js-md5"; export const LookupWidget = () => { const { EnjoyApp } = useContext(AppSettingsProviderContext); @@ -104,15 +105,16 @@ export const AiLookupResult = (props: { sourceId?: string; }) => { const { word, context = "", sourceType, sourceId } = props; - const { webApi } = useContext(AppSettingsProviderContext); + const { webApi, EnjoyApp } = useContext(AppSettingsProviderContext); const [lookingUp, setLookingUp] = useState(false); const [result, setResult] = useState(); const { lookupWord } = useAiCommand(); - const handleLookup = async () => { + const handleLookup = async (options?: { force: boolean }) => { if (lookingUp) return; if (!word) return; + const { force = false } = options; setLookingUp(true); lookupWord({ @@ -120,6 +122,8 @@ export const AiLookupResult = (props: { context, sourceId, sourceType, + cacheKey: `lookup-${md5(`${word}-${context}`)}`, + force, }) .then((lookup) => { if (lookup?.meaning) { @@ -134,26 +138,36 @@ export const AiLookupResult = (props: { }); }; + const fetchCachedLookup = async () => { + const remoteLookup = await webApi.lookup({ + word, + context, + sourceId, + sourceType, + }); + if (remoteLookup?.meaning) { + setResult(remoteLookup); + return; + } + + const cached = await EnjoyApp.cacheObjects.get( + `lookup-${md5(`${word}-${context}`)}` + ); + if (cached?.meaning) { + setResult(cached); + return; + } + + setResult(undefined); + }; + /* * Fetch cached lookup result. */ useEffect(() => { if (!word) return; - webApi - .lookup({ - word, - context, - sourceId, - sourceType, - }) - .then((res) => { - if (res?.meaning) { - setResult(res); - } else { - setResult(null); - } - }); + fetchCachedLookup(); }, [word, context]); if (!word) return null; @@ -164,34 +178,53 @@ export const AiLookupResult = (props: { {t("aiDictionary")} {result ? ( -
-
{word}
-
- {result.meaning?.pos && ( - - {result.meaning.pos} - - )} - {result.meaning?.pronunciation && ( - - /{result.meaning.pronunciation.replaceAll("/", "")}/ - - )} - {result.meaning?.lemma && - result.meaning.lemma !== result.meaning.word && ( - ({result.meaning.lemma}) + <> +
+
{word}
+
+ {result.meaning?.pos && ( + + {result.meaning.pos} + )} + {result.meaning?.pronunciation && ( + + /{result.meaning.pronunciation.replaceAll("/", "")}/ + + )} + {result.meaning?.lemma && + result.meaning.lemma !== result.meaning.word && ( + ({result.meaning.lemma}) + )} +
+
{result.meaning.translation}
+
{result.meaning.definition}
-
{result.meaning.translation}
-
{result.meaning.definition}
-
+
+ +
+ ) : (