From 57d3f69efad74ebcf6d7adeed7a57811cb67a9fa Mon Sep 17 00:00:00 2001 From: Isra Date: Sat, 16 Mar 2024 14:55:29 -0500 Subject: [PATCH 1/7] Drop subtitles --- src/assets/locales/en.json | 2 +- src/components/DropFile.tsx | 51 +++++++++++++++++++ .../player/atoms/settings/CaptionsView.tsx | 32 +++++++++++- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 src/components/DropFile.tsx diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index dc4d6ed1..59bc992d 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -316,7 +316,7 @@ "unknownOption": "Unknown" }, "subtitles": { - "customChoice": "Select subtitle from file", + "customChoice": "Drop or upload file", "customizeLabel": "Customize", "offChoice": "Off", "settings": { diff --git a/src/components/DropFile.tsx b/src/components/DropFile.tsx new file mode 100644 index 00000000..b432c2ce --- /dev/null +++ b/src/components/DropFile.tsx @@ -0,0 +1,51 @@ +import { useEffect, useState } from "react"; +import type { DragEvent, ReactNode } from "react"; + +interface FileDropHandlerProps { + children: ReactNode; + className: string; + onDrop: (event: DragEvent) => void; + onDraggingChange: (isDragging: boolean) => void; +} + +export function FileDropHandler(props: FileDropHandlerProps) { + const [dragging, setDragging] = useState(false); + + const handleDragEnter = (event: DragEvent) => { + event.preventDefault(); + setDragging(true); + }; + + const handleDragLeave = (event: DragEvent) => { + if (!event.currentTarget.contains(event.relatedTarget as Node)) { + setDragging(false); + } + }; + + const handleDragOver = (event: DragEvent) => { + event.preventDefault(); + }; + + const handleDrop = (event: DragEvent) => { + event.preventDefault(); + setDragging(false); + + props.onDrop(event); + }; + + useEffect(() => { + props.onDraggingChange(dragging); + }, [dragging, props]); + + return ( +
+ {props.children} +
+ ); +} diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index 8524ecc8..627787ba 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -5,6 +5,7 @@ import { useAsyncFn } from "react-use"; import { convert } from "subsrt-ts"; import { subtitleTypeList } from "@/backend/helpers/subs"; +import { FileDropHandler } from "@/components/DropFile"; import { FlagIcon } from "@/components/FlagIcon"; import { useCaptions } from "@/components/player/hooks/useCaptions"; import { Menu } from "@/components/player/internals/ContextMenu"; @@ -123,6 +124,8 @@ export function CaptionsView({ id }: { id: string }) { const { selectCaptionById, disable } = useCaptions(); const captionList = usePlayerStore((s) => s.captionList); const getHlsCaptionList = usePlayerStore((s) => s.display?.getCaptionList); + const [dragging, setDragging] = useState(false); + const setCaption = usePlayerStore((s) => s.setCaption); const captions = useMemo( () => @@ -162,7 +165,31 @@ 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]); + }} + >
router.navigate("/")} @@ -182,6 +209,7 @@ export function CaptionsView({ id }: { id: string }) {
+ disable()} selected={!selectedCaptionId}> {t("player.menus.subtitles.offChoice")} @@ -189,7 +217,7 @@ export function CaptionsView({ id }: { id: string }) { {content} - +
); } From c9d2d7134bbd3a01e6323b8993ae3d3802aea352 Mon Sep 17 00:00:00 2001 From: Isra Date: Mon, 18 Mar 2024 13:41:10 -0500 Subject: [PATCH 2/7] Fix issues --- src/assets/locales/en.json | 3 +- src/components/DropFile.tsx | 4 +- .../player/atoms/settings/CaptionsView.tsx | 96 ++++++++++++------- 3 files changed, 64 insertions(+), 39 deletions(-) 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} + +
+ ); } From a26097ffd4cdbeced29b7830a63464f2a792b725 Mon Sep 17 00:00:00 2001 From: Isra Date: Mon, 18 Mar 2024 13:47:05 -0500 Subject: [PATCH 3/7] Bold and change size --- src/components/player/atoms/settings/CaptionsView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index a3196929..62fc4ac7 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -197,8 +197,8 @@ export function CaptionsView({ id }: { id: string }) { {dragging && (
- - + + {t("player.menus.subtitles.dropSubtitleFile")}
From a172322a54071a25bf318b8645edf4f030fc253a Mon Sep 17 00:00:00 2001 From: Isra Date: Mon, 18 Mar 2024 15:50:56 -0500 Subject: [PATCH 4/7] Animate show/hide --- .../player/atoms/settings/CaptionsView.tsx | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index 62fc4ac7..37a5fa6e 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -1,3 +1,4 @@ +import classNames from "classnames"; import Fuse from "fuse.js"; import { type DragEvent, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -194,16 +195,19 @@ export function CaptionsView({ id }: { id: string }) { return ( <>
- {dragging && ( -
-
- - - {t("player.menus.subtitles.dropSubtitleFile")} - -
+
+
+ + + {t("player.menus.subtitles.dropSubtitleFile")} +
- )} +
router.navigate("/")} From b2ec99c4d19add5a6216657abdf4a6db4d338482 Mon Sep 17 00:00:00 2001 From: Isra Date: Mon, 18 Mar 2024 22:08:58 -0500 Subject: [PATCH 5/7] Make bg darker --- src/components/player/atoms/settings/CaptionsView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index 37a5fa6e..88614c71 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -225,7 +225,7 @@ export function CaptionsView({ id }: { id: string }) {
{ setDragging(isDragging); }} From e54077045df9cf6e0feb8c117ec6bf2b7082a1ba Mon Sep 17 00:00:00 2001 From: Isra Date: Tue, 26 Mar 2024 00:29:47 -0500 Subject: [PATCH 6/7] Change icon --- src/components/Icon.tsx | 2 ++ src/components/player/atoms/settings/CaptionsView.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index ec5e26cb..500b408a 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -64,6 +64,7 @@ export enum Icons { DONATION = "donation", CIRCLE_QUESTION = "circle_question", BRUSH = "brush", + UPLOAD = "upload", } export interface IconProps { @@ -134,6 +135,7 @@ const iconList: Record = { donation: ``, circle_question: ``, brush: ``, + upload: ``, }; function ChromeCastButton() { diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index 88614c71..035567e2 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -202,7 +202,7 @@ export function CaptionsView({ id }: { id: string }) { )} >
- + {t("player.menus.subtitles.dropSubtitleFile")} From 42d107dd9d50d6dd6f887b5782bc1e843002b1a3 Mon Sep 17 00:00:00 2001 From: qtchaos <72168435+qtchaos@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:45:24 +0200 Subject: [PATCH 7/7] fix: stop failed test from leaking worker url --- src/pages/parts/admin/WorkerTestPart.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/parts/admin/WorkerTestPart.tsx b/src/pages/parts/admin/WorkerTestPart.tsx index 5f8b9853..bb68fced 100644 --- a/src/pages/parts/admin/WorkerTestPart.tsx +++ b/src/pages/parts/admin/WorkerTestPart.tsx @@ -83,10 +83,12 @@ export function WorkerTestPart() { status: "success", }); } catch (err) { + const error = err as Error; + error.message = error.message.replace(worker.url, "WORKER_URL"); updateWorker(worker.id, { id: worker.id, status: "error", - error: err as Error, + error, }); } });