diff --git a/enjoy/src/renderer/components/audios/audio-player.tsx b/enjoy/src/renderer/components/audios/audio-player.tsx index d4d931c3..84128a77 100644 --- a/enjoy/src/renderer/components/audios/audio-player.tsx +++ b/enjoy/src/renderer/components/audios/audio-player.tsx @@ -43,7 +43,7 @@ export const AudioPlayer = (props: { return () => { setCurrentSegmentIndex(0); }; - }, [media]); + }, [media?.id]); if (!audio) return null; if (!layout) return ; diff --git a/enjoy/src/renderer/components/courses/chapter-content.tsx b/enjoy/src/renderer/components/courses/chapter-content.tsx index f686d29b..54bf76c2 100644 --- a/enjoy/src/renderer/components/courses/chapter-content.tsx +++ b/enjoy/src/renderer/components/courses/chapter-content.tsx @@ -84,7 +84,9 @@ export const ChapterContent = (props: {
-

{chapter?.title}

+

+ {chapter.sequence}. {chapter?.title} +

{chapter?.content} {translation && (
@@ -96,9 +98,7 @@ export const ChapterContent = (props: { {chapter.examples.length > 0 && ( <>

{t("examples")}

-
- {t("howToFinishChapter")} -
+
{t("howToFinishChapter")}
)}
diff --git a/enjoy/src/renderer/components/medias/media-caption.tsx b/enjoy/src/renderer/components/medias/media-caption.tsx index e5b3f60b..afc0aff2 100644 --- a/enjoy/src/renderer/components/medias/media-caption.tsx +++ b/enjoy/src/renderer/components/medias/media-caption.tsx @@ -355,6 +355,7 @@ export const MediaCaption = () => { }; }, []); + if (!transcription) return null; if (!caption) return null; return ( diff --git a/enjoy/src/renderer/components/medias/media-provider.tsx b/enjoy/src/renderer/components/medias/media-provider.tsx index a7006643..74c426f6 100644 --- a/enjoy/src/renderer/components/medias/media-provider.tsx +++ b/enjoy/src/renderer/components/medias/media-provider.tsx @@ -44,12 +44,17 @@ export const MediaProvider = () => { player.current.textTracks.clear(); player.current.textTracks.add( new TextTrack({ + label: "Transcription", content: srt, kind: "subtitles", type: "srt", language: transcription.result.language, }) ); + + return () => { + setMediaProvider(null); + }; }, [player, transcription]); if (!media?.src) return null; diff --git a/enjoy/src/renderer/components/pronunciation-assessments/pronunciation-assessment-form.tsx b/enjoy/src/renderer/components/pronunciation-assessments/pronunciation-assessment-form.tsx index 37d8f557..bbd93bfc 100644 --- a/enjoy/src/renderer/components/pronunciation-assessments/pronunciation-assessment-form.tsx +++ b/enjoy/src/renderer/components/pronunciation-assessments/pronunciation-assessment-form.tsx @@ -98,7 +98,7 @@ export const PronunciationAssessmentForm = () => { } else { arrayBuffer = await new Blob([file[0]]).arrayBuffer(); } - const recording = await EnjoyApp.recordings.create({ + return await EnjoyApp.recordings.create({ language, referenceText, blob: { @@ -106,15 +106,6 @@ export const PronunciationAssessmentForm = () => { arrayBuffer, }, }); - - try { - await EnjoyApp.recordings.sync(recording.id); - return recording; - } catch (err) { - toast.error(err.message); - EnjoyApp.recordings.destroy(recording.id); - return; - } }; return ( diff --git a/enjoy/src/renderer/components/transcriptions/transcription-create-form.tsx b/enjoy/src/renderer/components/transcriptions/transcription-create-form.tsx index 5beb3df3..6df04c57 100644 --- a/enjoy/src/renderer/components/transcriptions/transcription-create-form.tsx +++ b/enjoy/src/renderer/components/transcriptions/transcription-create-form.tsx @@ -3,11 +3,14 @@ import { AppSettingsProviderContext, } from "@renderer/context"; import { zodResolver } from "@hookform/resolvers/zod"; -import { useContext } from "react"; +import { useContext, useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { Button, + Collapsible, + CollapsibleContent, + CollapsibleTrigger, Form, FormDescription, FormField, @@ -28,7 +31,7 @@ import { } from "@renderer/components/ui"; import { t } from "i18next"; import { LANGUAGES } from "@/constants"; -import { LoaderIcon } from "lucide-react"; +import { ChevronDownIcon, ChevronUpIcon, LoaderIcon } from "lucide-react"; import { parseText } from "media-captions"; import { milisecondsToTimestamp } from "@/utils"; @@ -67,6 +70,7 @@ export const TranscriptionCreateForm = (props: { isolate: false, }, }); + const [collapsibleOpen, setCollapsibleOpen] = useState(false); const handleSubmit = (data: z.infer) => { const { service, text } = data; @@ -218,30 +222,6 @@ export const TranscriptionCreateForm = (props: { name="text" render={({ field }) => ( - {t("uploadTranscriptFile")} - { - const file = event.target.files[0]; - - if (file) { - parseSubtitle(file) - .then((text) => { - field.onChange(text); - }) - .catch((error) => { - toast.error(error.message); - }); - } else { - field.onChange(""); - } - }} - /> - - {t("uploadTranscriptFileDescription")} - {field.value != undefined && ( <> {t("transcript")} @@ -256,6 +236,44 @@ export const TranscriptionCreateForm = (props: { )} /> + + )} + + + {form.watch("service") === "upload" && ( + ( + + {t("uploadTranscriptFile")} + { + const file = event.target.files[0]; + + if (file) { + parseSubtitle(file) + .then((text) => { + field.onChange(text); + }) + .catch((error) => { + toast.error(error.message); + }); + } else { + field.onChange(""); + } + }} + /> + + {t("uploadTranscriptFileDescription")} + + + )} + /> + )} )} /> - - )} + +
+ + + +
+
Shadow + diff --git a/enjoy/src/renderer/context/media-player-provider.tsx b/enjoy/src/renderer/context/media-player-provider.tsx index 12c7656a..4f6ef78d 100644 --- a/enjoy/src/renderer/context/media-player-provider.tsx +++ b/enjoy/src/renderer/context/media-player-provider.tsx @@ -194,9 +194,10 @@ export const MediaPlayerProvider = ({ const getCachedSegmentIndex = async () => { if (!media) return; - const index = await EnjoyApp.cacheObjects.get( - `${media.mediaType.toLowerCase()}-${media.id}-last-segment-index` - ); + const cachedId = `${media.mediaType.toLowerCase()}-${ + media.id + }-last-segment-index`; + const index = await EnjoyApp.cacheObjects.get(cachedId); return index || 0; }; @@ -204,10 +205,10 @@ export const MediaPlayerProvider = ({ const setCachedSegmentIndex = (index: number) => { if (!media) return; - return EnjoyApp.cacheObjects.set( - `${media.mediaType.toLowerCase()}-${media.id}-last-segment-index`, - index - ); + const cachedId = `${media.mediaType.toLowerCase()}-${ + media.id + }-last-segment-index`; + return EnjoyApp.cacheObjects.set(cachedId, index); }; const { notes, createNote } = useNotes({ @@ -563,7 +564,7 @@ export const MediaPlayerProvider = ({ /* cache last segment index */ useEffect(() => { if (!media) return; - if (!currentSegmentIndex) return; + if (typeof currentSegmentIndex !== "number") return; setCachedSegmentIndex(currentSegmentIndex); }, [currentSegmentIndex]); diff --git a/enjoy/src/renderer/hooks/use-transcriptions.tsx b/enjoy/src/renderer/hooks/use-transcriptions.tsx index ba72684b..61095acc 100644 --- a/enjoy/src/renderer/hooks/use-transcriptions.tsx +++ b/enjoy/src/renderer/hooks/use-transcriptions.tsx @@ -208,46 +208,6 @@ export const useTranscriptions = (media: AudioType | VideoType) => { return timeline; }; - const findTranscriptionFromWebApi = async () => { - if (!transcription) { - await findOrCreateTranscription(); - } - - const res = await webApi.transcriptions({ - targetMd5: media.md5, - }); - - const transcript = (res?.transcriptions || []).filter((t) => - ["base", "small", "medium", "large", "whisper-1", "original"].includes( - t.model - ) - )?.[0]; - - if (!transcript) { - return Promise.reject("Transcription not found"); - } - - if (!transcript.result["timeline"]) { - return Promise.reject("Transcription not aligned"); - } - - return EnjoyApp.transcriptions.update(transcription.id, { - state: "finished", - result: transcript.result, - engine: transcript.engine, - model: transcript.model, - }); - }; - - const findOrGenerateTranscription = async () => { - try { - await findTranscriptionFromWebApi(); - } catch (err) { - console.warn(err); - await generateTranscription(); - } - }; - /* * find or create transcription */