6 changed files with 179 additions and 88 deletions
@ -0,0 +1,63 @@
@@ -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 @@
@@ -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