Improve: update media tab content translation (#1044)

* refactor: rename files

* update lookup result

* fix style
This commit is contained in:
an-lee
2024-09-06 19:10:31 +08:00
committed by GitHub
parent fffb97f8dc
commit 21a8ea5d1f
6 changed files with 146 additions and 143 deletions

View File

@@ -1,4 +1,4 @@
export * from "./media-caption-tabs";
export * from "./tab-content-analysis";
export * from "./tab-content-note";
export * from "./tab-content-translation";
export * from "./media-tab-content-analysis";
export * from "./media-tab-content-note";
export * from "./media-tab-content-translation";

View File

@@ -7,9 +7,9 @@ import {
} from "@renderer/components/ui";
import { t } from "i18next";
import { TimelineEntry } from "echogarden/dist/utilities/Timeline.d.js";
import { TabContentTranslation } from "./tab-content-translation";
import { TabContentAnalysis } from "./tab-content-analysis";
import { TabContentNote } from "./tab-content-note";
import { MediaTabContentTranslation } from "./media-tab-content-translation";
import { MediaTabContentAnalysis } from "./media-tab-content-analysis";
import { MediaTabContentNote } from "./media-tab-content-note";
export const MediaCaptionTabs = (props: {
caption: TimelineEntry;
@@ -38,18 +38,18 @@ export const MediaCaptionTabs = (props: {
{children}
<div className="px-4 pb-10 min-h-32">
<TabContentNote
<MediaTabContentNote
currentSegmentIndex={currentSegmentIndex}
selectedIndices={selectedIndices}
setSelectedIndices={setSelectedIndices}
/>
<TabContentTranslation
<MediaTabContentTranslation
caption={caption}
selectedIndices={selectedIndices}
/>
<TabContentAnalysis text={caption.text} />
<MediaTabContentAnalysis text={caption.text} />
</div>
<TabsList className="grid grid-cols-3 gap-4 rounded-none absolute w-full bottom-0 px-4">

View File

@@ -9,7 +9,7 @@ import { LoaderIcon } from "lucide-react";
import { md5 } from "js-md5";
import Markdown from "react-markdown";
export function TabContentAnalysis(props: { text: string; }) {
export function MediaTabContentAnalysis(props: { text: string }) {
const { text } = props;
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const [analyzing, setAnalyzing] = useState<boolean>(false);
@@ -55,7 +55,7 @@ export function TabContentAnalysis(props: { text: string; }) {
new URL(props.href ?? "");
props.target = "_blank";
props.rel = "noopener noreferrer";
} catch (e) { }
} catch (e) {}
return <a {...props}>{children}</a>;
},
@@ -82,8 +82,9 @@ export function TabContentAnalysis(props: { text: string; }) {
const result = replies.map((m) => m.content).join("\n");
setAnalysisResult(result);
EnjoyApp.cacheObjects.set(`analyze-${md5(text)}`, result);
} }
tooltip={t("useAIAssistantToAnalyze")} />
}}
tooltip={t("useAIAssistantToAnalyze")}
/>
</div>
</>
) : (
@@ -98,8 +99,9 @@ export function TabContentAnalysis(props: { text: string; }) {
const result = replies.map((m) => m.content).join("\n");
setAnalysisResult(result);
EnjoyApp.cacheObjects.set(`analyze-${md5(text)}`, result);
} }
tooltip={t("useAIAssistantToAnalyze")} />
}}
tooltip={t("useAIAssistantToAnalyze")}
/>
</div>
)}
</TabsContent>

View File

@@ -7,7 +7,7 @@ import { NoteCard, NoteForm } from "@renderer/components";
/*
* Note tab content.
*/
export const TabContentNote = (props: {
export const MediaTabContentNote = (props: {
currentSegmentIndex: number;
selectedIndices: number[];
setSelectedIndices: (indices: number[]) => void;

View File

@@ -0,0 +1,128 @@
import { useContext } from "react";
import {
AppSettingsProviderContext,
MediaPlayerProviderContext,
DictProviderContext,
} from "@renderer/context";
import { TabsContent, Separator } from "@renderer/components/ui";
import { t } from "i18next";
import { TimelineEntry } from "echogarden/dist/utilities/Timeline.d.js";
import { convertWordIpaToNormal } from "@/utils";
import {
CamdictLookupResult,
DictLookupResult,
AiLookupResult,
TranslateResult,
DictSelect,
} from "@renderer/components";
/*
* Translation tab content.
*/
export function MediaTabContentTranslation(props: {
caption: TimelineEntry;
selectedIndices: number[];
}) {
const { caption } = props;
return (
<TabsContent value="translation">
<SelectedWords {...props} />
<Separator className="my-4" />
<div className="text-sm italic text-muted-foreground mb-2">
{t("translateSentence")}
</div>
<TranslateResult text={caption.text} />
</TabsContent>
);
}
const SelectedWords = (props: {
caption: TimelineEntry;
selectedIndices: number[];
}) => {
const { selectedIndices, caption } = props;
const { currentDictValue } = useContext(DictProviderContext);
const { transcription } = useContext(MediaPlayerProviderContext);
const { learningLanguage, ipaMappings } = useContext(
AppSettingsProviderContext
);
const word = selectedIndices
.map((index) => caption.timeline[index]?.text || "")
.join(" ")
.trim();
if (selectedIndices.length === 0)
return (
<div className="text-sm text-muted-foreground py-4">
{t("clickAnyWordToSelect")}
</div>
);
return (
<>
<div className="flex justify-between items-start flex-wrap">
<div className="flex flex-1 flex-wrap items-center space-x-2 select-text mb-4">
{selectedIndices.map((index, i) => {
const word = caption.timeline[index];
if (!word) return;
return (
<div key={index}>
<div className="font-serif text-lg font-semibold tracking-tight">
{word.text}
</div>
{word.timeline.length > 0 && (
<div className="text-sm text-serif text-muted-foreground">
<span
className={`mr-2 font-code ${
i === 0 ? "before:content-['/']" : ""
}
${
i === selectedIndices.length - 1
? "after:content-['/']"
: ""
}`}
>
{word.timeline
.map((t) =>
learningLanguage.startsWith("en")
? convertWordIpaToNormal(
t.timeline.map((s) => s.text),
{
mappings: ipaMappings,
}
).join("")
: t.text
)
.join(" ")}
</span>
</div>
)}
</div>
);
})}
</div>
<div className="w-60">
<DictSelect />
</div>
</div>
<Separator className="my-4" />
{currentDictValue === "cambridge" ? (
<CamdictLookupResult word={word} />
) : currentDictValue === "ai" ? (
<AiLookupResult
word={word}
context={caption.text}
sourceId={transcription.targetId}
sourceType={transcription.targetType}
/>
) : (
<DictLookupResult word={word} autoHeight={true} />
)}
</>
);
};

View File

@@ -1,127 +0,0 @@
import { useContext } from "react";
import {
AppSettingsProviderContext,
MediaPlayerProviderContext,
DictProviderContext,
} from "@renderer/context";
import { TabsContent, Separator } from "@renderer/components/ui";
import { t } from "i18next";
import { TimelineEntry } from "echogarden/dist/utilities/Timeline.d.js";
import { convertWordIpaToNormal } from "@/utils";
import {
CamdictLookupResult,
DictLookupResult,
AiLookupResult,
TranslateResult,
} from "@renderer/components";
/*
* Translation tab content.
*/
export function TabContentTranslation(props: {
caption: TimelineEntry;
selectedIndices: number[];
}) {
const { caption } = props;
return (
<TabsContent value="translation">
<SelectedWords {...props} />
<Separator className="my-2" />
<div className="text-sm italic text-muted-foreground mb-2">
{t("translateSentence")}
</div>
<TranslateResult text={caption.text} />
</TabsContent>
);
}
const SelectedWords = (props: {
caption: TimelineEntry;
selectedIndices: number[];
}) => {
const { selectedIndices, caption } = props;
const { currentDictValue } = useContext(DictProviderContext);
const { transcription } = useContext(MediaPlayerProviderContext);
const { learningLanguage, ipaMappings } = useContext(
AppSettingsProviderContext
);
const word = selectedIndices
.map((index) => caption.timeline[index]?.text || "")
.join(" ")
.trim();
if (selectedIndices.length === 0)
return (
<div className="text-sm text-muted-foreground py-4">
{t("clickAnyWordToSelect")}
</div>
);
return (
<>
<div className="flex flex-wrap items-center space-x-2 select-text mb-4">
{selectedIndices.map((index, i) => {
const word = caption.timeline[index];
if (!word) return;
return (
<div key={index}>
<div className="font-serif text-lg font-semibold tracking-tight">
{word.text}
</div>
{word.timeline.length > 0 && (
<div className="text-sm text-serif text-muted-foreground">
<span
className={`mr-2 font-code ${
i === 0 ? "before:content-['/']" : ""
}
${
i === selectedIndices.length - 1
? "after:content-['/']"
: ""
}`}
>
{word.timeline
.map((t) =>
learningLanguage.startsWith("en")
? convertWordIpaToNormal(
t.timeline.map((s) => s.text),
{
mappings: ipaMappings,
}
).join("")
: t.text
)
.join(" ")}
</span>
</div>
)}
</div>
);
})}
</div>
{currentDictValue === "cambridge" ? (
<>
<Separator className="my-2" />
<CamdictLookupResult word={word} />
</>
) : (
<>
<Separator className="my-2" />
<DictLookupResult word={word} autoHeight={true} />
</>
)}
<Separator className="my-2" />
<AiLookupResult
word={word}
context={caption.text}
sourceId={transcription.targetId}
sourceType={transcription.targetType}
/>
</>
);
};