6 changed files with 179 additions and 88 deletions
@ -0,0 +1,63 @@ |
|||||||
|
import { useCallback } from "react"; |
||||||
|
|
||||||
|
import { downloadSrt, searchSubtitles } from "@/backend/helpers/subs"; |
||||||
|
import { usePlayerStore } from "@/stores/player/store"; |
||||||
|
import { useSubtitleStore } from "@/stores/subtitles"; |
||||||
|
|
||||||
|
export function useCaptions() { |
||||||
|
const setLanguage = useSubtitleStore((s) => s.setLanguage); |
||||||
|
const enabled = useSubtitleStore((s) => s.enabled); |
||||||
|
const setCaption = usePlayerStore((s) => s.setCaption); |
||||||
|
const lastSelectedLanguage = useSubtitleStore((s) => s.lastSelectedLanguage); |
||||||
|
const meta = usePlayerStore((s) => s.meta); |
||||||
|
|
||||||
|
const download = useCallback( |
||||||
|
async (subtitleId: string, language: string) => { |
||||||
|
const srtData = await downloadSrt(subtitleId); |
||||||
|
setCaption({ |
||||||
|
language, |
||||||
|
srtData, |
||||||
|
url: "", // TODO remove url
|
||||||
|
}); |
||||||
|
setLanguage(language); |
||||||
|
}, |
||||||
|
[setCaption, setLanguage] |
||||||
|
); |
||||||
|
|
||||||
|
const search = useCallback(async () => { |
||||||
|
if (!meta) throw new Error("No meta"); |
||||||
|
return searchSubtitles(meta); |
||||||
|
}, [meta]); |
||||||
|
|
||||||
|
const disable = useCallback(async () => { |
||||||
|
setCaption(null); |
||||||
|
setLanguage(null); |
||||||
|
}, [setCaption, setLanguage]); |
||||||
|
|
||||||
|
const downloadLastUsed = useCallback(async () => { |
||||||
|
const language = lastSelectedLanguage ?? "en"; |
||||||
|
const searchResult = await search(); |
||||||
|
const languageResult = searchResult.find( |
||||||
|
(v) => v.attributes.language === language |
||||||
|
); |
||||||
|
if (!languageResult) return false; |
||||||
|
await download( |
||||||
|
languageResult.attributes.legacy_subtitle_id, |
||||||
|
languageResult.attributes.language |
||||||
|
); |
||||||
|
return true; |
||||||
|
}, [lastSelectedLanguage, search, download]); |
||||||
|
|
||||||
|
const toggleLastUsed = useCallback(async () => { |
||||||
|
if (!enabled) await downloadLastUsed(); |
||||||
|
else disable(); |
||||||
|
}, [downloadLastUsed, disable, enabled]); |
||||||
|
|
||||||
|
return { |
||||||
|
download, |
||||||
|
search, |
||||||
|
disable, |
||||||
|
downloadLastUsed, |
||||||
|
toggleLastUsed, |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
import { Icon, Icons } from "@/components/Icon"; |
||||||
|
|
||||||
|
export function Input(props: { |
||||||
|
value: string; |
||||||
|
onInput: (str: string) => void; |
||||||
|
}) { |
||||||
|
return ( |
||||||
|
<div className="w-full relative mb-6"> |
||||||
|
<Icon |
||||||
|
className="pointer-events-none absolute top-1/2 left-3 transform -translate-y-1/2 text-video-context-inputPlaceholder" |
||||||
|
icon={Icons.SEARCH} |
||||||
|
/> |
||||||
|
<input |
||||||
|
placeholder="Search" |
||||||
|
className="w-full py-2 px-3 pl-[calc(0.75rem+24px)] bg-video-context-inputBg rounded placeholder:text-video-context-inputPlaceholder" |
||||||
|
value={props.value} |
||||||
|
onInput={(e) => props.onInput(e.currentTarget.value)} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
Loading…
Reference in new issue