diff --git a/src/components/player/atoms/settings/LanguageSubtitlesView.tsx b/src/components/player/atoms/settings/LanguageSubtitlesView.tsx index f4cad7d8..ccdbab45 100644 --- a/src/components/player/atoms/settings/LanguageSubtitlesView.tsx +++ b/src/components/player/atoms/settings/LanguageSubtitlesView.tsx @@ -1,8 +1,9 @@ -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { useAsyncFn } from "react-use"; 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 { useOverlayRouter } from "@/hooks/useOverlayRouter"; @@ -30,7 +31,27 @@ export function LanguageSubtitlesView({ const [currentlyDownloading, setCurrentlyDownloading] = useState< string | null >(null); + const [scrollTrigger, setScrollTrigger] = useState(0); const captionList = usePlayerStore((s) => s.captionList); + + // Trigger scroll when selected caption changes + useEffect(() => { + if (selectedCaptionId) { + setScrollTrigger((prev) => prev + 1); + } + }, [selectedCaptionId]); + + // Manual scroll function with smooth behavior + const scrollToActiveCaption = () => { + const active = document.querySelector("[data-active-link]"); + if (!active) return; + + active.scrollIntoView({ + behavior: "smooth", + block: "center", + }); + }; + const getHlsCaptionList = usePlayerStore((s) => s.display?.getCaptionList); const isLoadingExternalSubtitles = usePlayerStore( (s) => s.isLoadingExternalSubtitles, @@ -58,6 +79,19 @@ export function LanguageSubtitlesView({ [selectCaptionById, setCurrentlyDownloading], ); + // Random subtitle selection + const handleRandomSelect = async () => { + if (languageCaptions.length === 0) return; + + const randomIndex = Math.floor(Math.random() * languageCaptions.length); + const randomCaption = languageCaptions[randomIndex]; + + await startDownload(randomCaption.id); + + // Scroll to the newly selected caption after a brief delay to ensure DOM updates + setTimeout(() => scrollToActiveCaption(), 100); + }; + // Render subtitle option const renderSubtitleOption = (v: CaptionListItem) => { const handleDoubleClick = async () => { @@ -119,6 +153,18 @@ export function LanguageSubtitlesView({ onClick={() => router.navigate(overlayBackLink ? "/captionsOverlay" : "/captions") } + rightSide={ + languageCaptions.length > 0 && ( + + ) + } > @@ -126,7 +172,10 @@ export function LanguageSubtitlesView({ - + 0} + > {languageCaptions.length > 0 ? ( languageCaptions.map(renderSubtitleOption) ) : ( diff --git a/src/components/player/internals/ContextMenu/Sections.tsx b/src/components/player/internals/ContextMenu/Sections.tsx index e2de0844..d0198b08 100644 --- a/src/components/player/internals/ContextMenu/Sections.tsx +++ b/src/components/player/internals/ContextMenu/Sections.tsx @@ -52,10 +52,11 @@ export function ScrollToActiveSection(props: { const activeYPos = activeLinkRect.top - boxRect.top; - scrollingContainer.current?.scrollTo( - 0, - activeYPos - boxRect.height / 2 + activeLinkRect.height / 2, - ); + scrollingContainer.current?.scrollTo({ + top: activeYPos - boxRect.height / 2 + activeLinkRect.height / 2, + left: 0, + behavior: "smooth", + }); }, [props.loaded]); return (