diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 59bc992d..bcb7e293 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -325,7 +325,8 @@ "fixCapitals": "Fix capitalization" }, "title": "Subtitles", - "unknownLanguage": "Unknown" + "unknownLanguage": "Unknown", + "dropSubtitleFile": "Drop subtitle file here" } }, "metadata": { diff --git a/src/components/DropFile.tsx b/src/components/DropFile.tsx index b432c2ce..8b0ab84e 100644 --- a/src/components/DropFile.tsx +++ b/src/components/DropFile.tsx @@ -38,7 +38,7 @@ export function FileDropHandler(props: FileDropHandlerProps) { }, [dragging, props]); return ( -
{props.children} -
+ ); } diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index 627787ba..a3196929 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -1,5 +1,5 @@ import Fuse from "fuse.js"; -import { useMemo, useRef, useState } from "react"; +import { type DragEvent, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useAsyncFn } from "react-use"; import { convert } from "subsrt-ts"; @@ -7,6 +7,7 @@ import { convert } from "subsrt-ts"; import { subtitleTypeList } from "@/backend/helpers/subs"; import { FileDropHandler } from "@/components/DropFile"; import { FlagIcon } from "@/components/FlagIcon"; +import { Icon, Icons } from "@/components/Icon"; import { useCaptions } from "@/components/player/hooks/useCaptions"; import { Menu } from "@/components/player/internals/ContextMenu"; import { Input } from "@/components/player/internals/ContextMenu/Input"; @@ -127,6 +128,32 @@ export function CaptionsView({ id }: { id: string }) { const [dragging, setDragging] = useState(false); const setCaption = usePlayerStore((s) => s.setCaption); + function onDrop(event: DragEvent) { + const files = event.dataTransfer.files; + const firstFile = files[0]; + if (!files || !firstFile) return; + + const fileExtension = `.${firstFile.name.split(".").pop()}`; + if (!fileExtension || !subtitleTypeList.includes(fileExtension)) { + return; + } + + const reader = new FileReader(); + reader.addEventListener("load", (e) => { + if (!e.target || typeof e.target.result !== "string") return; + + const converted = convert(e.target.result, "srt"); + + setCaption({ + language: "custom", + srtData: converted, + id: "custom-caption", + }); + }); + + reader.readAsText(firstFile); + } + const captions = useMemo( () => captionList.length !== 0 ? captionList : getHlsCaptionList?.() ?? [], @@ -165,32 +192,19 @@ export function CaptionsView({ id }: { id: string }) { }); return ( - { - setDragging(isDragging); - }} - onDrop={(event) => { - const files = event.dataTransfer.files; - if (!files || files.length === 0) return; - - const reader = new FileReader(); - reader.addEventListener("load", (e) => { - if (!e.target || typeof e.target.result !== "string") return; - - const converted = convert(e.target.result, "srt"); - - setCaption({ - language: "custom", - srtData: converted, - id: "custom-caption", - }); - }); - - reader.readAsText(files[0]); - }} - > + <>
+ {dragging && ( +
+
+ + + {t("player.menus.subtitles.dropSubtitleFile")} + +
+
+ )} + router.navigate("/")} rightSide={ @@ -205,19 +219,29 @@ export function CaptionsView({ id }: { id: string }) { > {t("player.menus.subtitles.title")} +
+ { + setDragging(isDragging); + }} + onDrop={(event) => onDrop(event)} + >
- - - - disable()} selected={!selectedCaptionId}> - {t("player.menus.subtitles.offChoice")} - - - {content} - -
+ + disable()} + selected={!selectedCaptionId} + > + {t("player.menus.subtitles.offChoice")} + + + {content} + +
+ ); }