import { getCaptionUrl, convertCustomCaptionFileToWebVTT, CUSTOM_CAPTION_ID, } from "@/backend/helpers/captions"; import { MWCaption } from "@/backend/helpers/streams"; import { Icon, Icons } from "@/components/Icon"; import { FloatingCardView } from "@/components/popout/FloatingCard"; import { FloatingView } from "@/components/popout/FloatingView"; import { useFloatingRouter } from "@/hooks/useFloatingRouter"; import { useLoading } from "@/hooks/useLoading"; import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useControls } from "@/video/state/logic/controls"; import { useMeta } from "@/video/state/logic/meta"; import { useSource } from "@/video/state/logic/source"; import { ChangeEvent, useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; import { PopoutListEntry, PopoutSection } from "./PopoutUtils"; function makeCaptionId(caption: MWCaption, isLinked: boolean): string { return isLinked ? `linked-${caption.langIso}` : `external-${caption.langIso}`; } export function CaptionSelectionPopout(props: { router: ReturnType; prefix: string; }) { const { t } = useTranslation(); const descriptor = useVideoPlayerDescriptor(); const meta = useMeta(descriptor); const source = useSource(descriptor); const controls = useControls(descriptor); const linkedCaptions = useMemo( () => meta?.captions.map((v) => ({ ...v, id: makeCaptionId(v, true) })) ?? [], [meta] ); const loadingId = useRef(""); const [setCaption, loading, error] = useLoading( async (caption: MWCaption, isLinked: boolean) => { const id = makeCaptionId(caption, isLinked); loadingId.current = id; controls.setCaption(id, await getCaptionUrl(caption)); controls.closePopout(); } ); const currentCaption = source.source?.caption?.id; const customCaptionUploadElement = useRef(null); const [setCustomCaption, loadingCustomCaption, errorCustomCaption] = useLoading(async (captionFile: File) => { if ( !captionFile.name.endsWith(".srt") && !captionFile.name.endsWith(".vtt") ) { throw new Error("Only SRT or VTT files are allowed"); } controls.setCaption( CUSTOM_CAPTION_ID, await convertCustomCaptionFileToWebVTT(captionFile) ); controls.closePopout(); }); async function handleUploadCaption(e: ChangeEvent) { if (!e.target.files) { return; } const captionFile = e.target.files[0]; setCustomCaption(captionFile); } return ( props.router.navigate("/")} action={ } /> { controls.clearCaption(); controls.closePopout(); }} > {t("videoPlayer.popouts.noCaptions")} { customCaptionUploadElement.current?.click(); }} > {currentCaption === CUSTOM_CAPTION_ID ? t("videoPlayer.popouts.customCaption") : t("videoPlayer.popouts.uploadCustomCaption")}

{t("videoPlayer.popouts.linkedCaptions")}

{linkedCaptions.map((link) => ( { loadingId.current = link.id; setCaption(link, true); }} > {link.langIso} ))}
); }