Skip to content

Commit

Permalink
Feat: improve player caption (#433)
Browse files Browse the repository at this point in the history
* update ipa mapping

* refactor player caption layout
  • Loading branch information
an-lee authored Mar 22, 2024
1 parent d2a777a commit 03d0815
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 134 deletions.
44 changes: 22 additions & 22 deletions enjoy/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ export const IPA_MAPPING: { [key: string]: string } = {
ʐ: "z",
ç: "",
ʝ: "j",
x: "h",
x: "k",
ɣ: "g",
χ: "h",
ʁ: "r",
Expand All @@ -420,7 +420,7 @@ export const IPA_MAPPING: { [key: string]: string } = {
ʈʃ: "tʃ",
: "dʒ",
ʋ: "v",
ɹ: "ɹ",
ɹ: "r",
ɻ: "r",
j: "j",
ɰ: "w",
Expand All @@ -437,58 +437,58 @@ export const IPA_MAPPING: { [key: string]: string } = {
ɪ: "ɪ",
ʏ: "ɪ",
ʊ: "ʊ",
ɨ: "ɪ",
: "ɪ",
ɨ: "i",
: "i:",
e: "e",
ø: "e",
ɘ: "ə",
ɵ: "ə",
ɤ: "ɒ",
ɤ: "ɑː",
o: "o",
ə: "ə",
: "oː",
ɛ: "ɛ",
ɛ: "e",
œ: "æ",
ɜ: "ɜ",
ɜ: "ɝ",
ɞ: "əː",
ʌ: "ʌ",
ɔ: "ɔ",
ɜː: "əː",
ɜː: "ɝː",
: "uː",
ɔː: "ɔː",
ɛː: "ɛ:",
ɛː: "e:",
æ: "æ",
a: "ɑ",
ɶ: "ɑ",
ɐ: "ə",
ɑ: "ɑ",
ɒ: "ɒ",
ɒ: "ɑː",
ɑː: "ɑː",
"◌˞": "",
ɚ: "ɚ",
ɝ: "ɝ",
ɹ̩: "r",
: "eɪ",
əʊ: "əʊ",
: "əʊ",
əʊ: "",
: "",
: "aɪ",
ɔɪ: "ɔɪ",
: "aʊ",
: "iə",
ɜr: "ɜr",
ɑr: "ɑr",
ɔr: "ɔr",
oʊr: "əʊr",
oːɹ: "ɔːɹ",
oʊr: "oʊr",
oːɹ: "ɔːr",
ir: "ir",
ɪɹ: "ɪɹ",
ɔːɹ: "ɔːɹ",
ɑːɹ: "ɑːɹ",
ʊɹ: "ʊɹ",
ʊr: "ʊɹ",
ɛr: "ɛr",
ɛɹ: "ɛɹ",
ɪɹ: "ɪr",
ɔːɹ: "ɔːr",
ɑːɹ: "ɑːr",
ʊɹ: "ʊr",
ʊr: "ʊr",
ɛr: "er",
ɛɹ: "er",
əl: "ə",
aɪɚ: "aɪ",
aɪə: "",
aɪə: "aɪə",
};
1 change: 1 addition & 0 deletions enjoy/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,5 +510,6 @@
"translateSetence": "translate setenece",
"reTranslate": "re-translate",
"analyzeSetence": "analyze setenece",
"useAIAssistantToAnalyze": "Use AI assistant to analyze",
"reAnalyze": "re-analyze"
}
1 change: 1 addition & 0 deletions enjoy/src/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -509,5 +509,6 @@
"translateSetence": "整句翻译",
"reTranslate": "重新翻译",
"analyzeSetence": "分析句子",
"useAIAssistantToAnalyze": "使用智能助手分析",
"reAnalyze": "重新分析"
}
2 changes: 1 addition & 1 deletion enjoy/src/renderer/components/audios/audio-player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const AudioPlayer = (props: { id?: string; md5?: string }) => {
return (
<div data-testid="audio-player">
<div className="h-[calc(100vh-37.5rem)] mb-4">
<div className="grid grid-cols-3 gap-4 px-6 h-full">
<div className="grid grid-cols-3 gap-6 px-6 h-full">
<div className="col-span-1 rounded-lg border shadow-lg h-[calc(100vh-37.5rem)]">
<MediaTabs />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { useNavigate } from "react-router-dom";

export const ConversationShortcuts = (props: {
trigger: React.ReactNode;
title?: string;
open?: boolean;
onOpenChange?: (open: boolean) => void;
prompt: string;
Expand All @@ -32,6 +33,7 @@ export const ConversationShortcuts = (props: {
}) => {
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const {
title,
prompt,
onReply,
excludedIds = [],
Expand Down Expand Up @@ -196,7 +198,7 @@ export const ConversationShortcuts = (props: {
<DialogTrigger asChild>{trigger}</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>{t("sendToAIAssistant")}</DialogTitle>
<DialogTitle>{title || t("sendToAIAssistant")}</DialogTitle>
</DialogHeader>
{dialogContent()}
</DialogContent>
Expand Down
97 changes: 54 additions & 43 deletions enjoy/src/renderer/components/medias/media-caption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ export const MediaCaption = () => {

return (
<div className="h-full flex justify-between space-x-4">
<ScrollArea className="flex-1 px-6 py-4 font-serif h-full border shadow-lg rounded-lg">
<div className="flex flex-wrap mb-4">
<ScrollArea className="flex-1 font-serif h-full border shadow-lg rounded-lg">
<div className="flex flex-wrap px-4 py-2">
{/* use the words splitted by caption text if it is matched with the timeline length, otherwise use the timeline */}
{caption.text.split(" ").length !== caption.timeline.length
? (caption.timeline || []).map((w, index) => (
Expand All @@ -300,10 +300,12 @@ export const MediaCaption = () => {
onClick={() => toggleRegion(index)}
>
<div className="">
<div className="text-2xl">{w.text}</div>
<div className="text-lg xl:text-xl 2xl:text-2xl">
{w.text}
</div>
{displayIpa && (
<div
className={`text-muted-foreground font-code ${
className={`text-sm 2xl:text-base text-muted-foreground font-code ${
index === 0 ? "before:content-['/']" : ""
}
${
Expand Down Expand Up @@ -334,10 +336,12 @@ export const MediaCaption = () => {
onClick={() => toggleRegion(index)}
>
<div className="">
<div className="text-2xl">{word}</div>
<div className="text-lg xl:text-xl 2xl:text-2xl">
{word}
</div>
{displayIpa && (
<div
className={`text-muted-foreground font-code ${
className={`text-sm 2xl:text-base text-muted-foreground font-code ${
index === 0 ? "before:content-['/']" : ""
}
${
Expand Down Expand Up @@ -371,18 +375,23 @@ export const MediaCaption = () => {
variant={displayIpa ? "secondary" : "outline"}
size="icon"
className="rounded-full w-8 h-8 p-0"
data-tooltip-id="media-player-controls-tooltip"
data-tooltip-id="media-player-tooltip"
data-tooltip-content={t("displayIpa")}
onClick={() => setDisplayIpa(!displayIpa)}
>
<SpeechIcon className="w-4 h-4" />
</Button>

<AIButton
prompt={caption.text as string}
tooltip={t("sendToAIAssistant")}
/>

<Button
variant="outline"
size="icon"
className="rounded-full w-8 h-8 p-0"
data-tooltip-id="media-player-controls-tooltip"
data-tooltip-id="media-player-tooltip"
data-tooltip-content={t("copyText")}
onClick={() => {
copyToClipboard(caption.text);
Expand All @@ -396,7 +405,7 @@ export const MediaCaption = () => {
<CheckIcon className="w-4 h-4 text-green-500" />
) : (
<CopyIcon
data-tooltip-id="media-player-controls-tooltip"
data-tooltip-id="media-player-tooltip"
data-tooltip-content={t("copyText")}
className="w-4 h-4"
/>
Expand Down Expand Up @@ -549,12 +558,8 @@ const CaptionTabs = (props: {
}, [caption]);

return (
<Tabs
value={tab}
onValueChange={(value) => setTab(value)}
className="border rounded-lg"
>
<TabsList className="grid grid-cols-4 gap-4 rounded-b-none sticky top-0">
<Tabs value={tab} onValueChange={(value) => setTab(value)} className="">
<TabsList className="grid grid-cols-4 gap-4 rounded-none sticky top-0 px-4 mb-4">
<TabsTrigger value="selected">{t("captionTabs.selected")}</TabsTrigger>
<TabsTrigger value="translation">
{t("captionTabs.translation")}
Expand All @@ -563,7 +568,7 @@ const CaptionTabs = (props: {
<TabsTrigger value="note">{t("captionTabs.note")}</TabsTrigger>
</TabsList>

<div className="px-4 pb-2 min-h-32">
<div className="px-4 pb-4 min-h-32">
<TabsContent value="selected">
{selectedIndices.length > 0 ? (
<>
Expand Down Expand Up @@ -631,7 +636,7 @@ const CaptionTabs = (props: {
</div>
</>
) : (
<div className="text-muted-foreground py-4">
<div className="text-sm text-muted-foreground py-4">
{t("clickAnyWordToSelect")}
</div>
)}
Expand All @@ -640,7 +645,11 @@ const CaptionTabs = (props: {
<TabsContent value="translation">
{translation ? (
<>
<div className="mb-2 flex items-center justify-end">
<Markdown className="select-text prose prose-sm prose-h3:text-base max-w-full mb-4">
{translation}
</Markdown>

<div className="flex items-center justify-end">
<Button
variant="secondary"
size="sm"
Expand All @@ -653,9 +662,6 @@ const CaptionTabs = (props: {
{t("reTranslate")}
</Button>
</div>
<div className="select-text text-sm text-foreground">
{translation}
</div>
</>
) : (
<div className="flex items-center justify-center space-x-2 py-4">
Expand All @@ -676,7 +682,24 @@ const CaptionTabs = (props: {
<TabsContent value="analysis">
{analysisResult ? (
<>
<div className="mb-2 flex items-center space-x-2 justify-end">
<Markdown
className="select-text prose prose-sm prose-h3:text-base max-w-full mb-4"
components={{
a({ node, children, ...props }) {
try {
new URL(props.href ?? "");
props.target = "_blank";
props.rel = "noopener noreferrer";
} catch (e) {}

return <a {...props}>{children}</a>;
},
}}
>
{analysisResult}
</Markdown>

<div className="flex items-center space-x-2 justify-end">
<Button
variant="secondary"
size="sm"
Expand All @@ -695,24 +718,9 @@ const CaptionTabs = (props: {
setAnalysisResult(result);
EnjoyApp.cacheObjects.set(`analyze-${hash}`, result);
}}
tooltip={t("useAIAssistantToAnalyze")}
/>
</div>
<Markdown
className="select-text prose prose-sm prose-h3:text-base max-w-full"
components={{
a({ node, children, ...props }) {
try {
new URL(props.href ?? "");
props.target = "_blank";
props.rel = "noopener noreferrer";
} catch (e) {}

return <a {...props}>{children}</a>;
},
}}
>
{analysisResult}
</Markdown>
</>
) : (
<div className="flex items-center justify-center space-x-2 py-4">
Expand All @@ -729,6 +737,7 @@ const CaptionTabs = (props: {
setAnalysisResult(result);
EnjoyApp.cacheObjects.set(`analyze-${hash}`, result);
}}
tooltip={t("useAIAssistantToAnalyze")}
/>
</div>
)}
Expand All @@ -746,25 +755,27 @@ const CaptionTabs = (props: {

const AIButton = (props: {
prompt: string;
onReply: (replies: MessageType[]) => void;
onReply?: (replies: MessageType[]) => void;
tooltip: string;
}) => {
const { prompt, onReply } = props;
const { prompt, onReply, tooltip } = props;
const [asking, setAsking] = useState<boolean>(false);
return (
<ConversationShortcuts
open={asking}
onOpenChange={setAsking}
prompt={prompt}
onReply={onReply}
title={tooltip}
trigger={
<Button
data-tooltip-id="media-player-controls-tooltip"
data-tooltip-content={t("sendToAIAssistant")}
data-tooltip-id="media-player-tooltip"
data-tooltip-content={tooltip}
variant="outline"
size="sm"
className="p-0 w-8 h-8 rounded-full"
>
<BotIcon className="w-5 h-5 text-muted-foreground hover:text-primary" />
<BotIcon className="w-5 h-5" />
</Button>
}
/>
Expand Down
Loading

0 comments on commit 03d0815

Please sign in to comment.