diff --git a/README.md b/README.md index a611b591..51c207c5 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ [![P-Stream Image](.github/P-Stream.png)](https://docs.pstream.mov) -**I _do not_ endorse piracy of any kind I simply enjoy programming and large user counts.** - ## Quick Deploy [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fp-stream%2Fp-stream) @@ -27,12 +25,7 @@ ## Referrers -- [FMHY (Voted as #1 multi-server streaming site of 2024)](https://fmhy.net) -- [Piracy Subreddit Megathread](https://www.reddit.com/r/Piracy/s/iymSloEpXn) -- [Toon's Instances](https://erynith.github.io/movie-web-instances) -- [Entertainment Empire](https://discord.gg/8NSDNEMfja) -- Search Engines: DuckDuckGo, Bing, Google -- Rentry.co +- [FMHY (Voted as #1 streaming site of 2024, 2025)](https://fmhy.net) ## Running Locally diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index df981271..f0a680a5 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -777,8 +777,8 @@ "refreshing": "Refreshing...", "empty": "There are no provided subtitles for this.", "notFound": "None of the available options match your query", - "useNativeSubtitles": "Use native video subtitles", - "useNativeSubtitlesDescription": "May fix subtitles when casting and in PiP", + "useNativeSubtitles": "Native video subtitles", + "useNativeSubtitlesDescription": "Broadcast subtitles for native fullscreen and PiP", "delayLate": "Heard audio", "delayEarly": "Saw caption" }, diff --git a/src/components/overlays/detailsModal/components/carousels/EpisodeCarousel.tsx b/src/components/overlays/detailsModal/components/carousels/EpisodeCarousel.tsx index 9fec2494..b6eeacb6 100644 --- a/src/components/overlays/detailsModal/components/carousels/EpisodeCarousel.tsx +++ b/src/components/overlays/detailsModal/components/carousels/EpisodeCarousel.tsx @@ -45,39 +45,6 @@ export function EpisodeCarousel({ const updateItem = useProgressStore((s) => s.updateItem); const confirmModal = useModal("season-watch-confirm"); - const [canScrollLeft, setCanScrollLeft] = useState(false); - const [canScrollRight, setCanScrollRight] = useState(false); - - const updateScrollState = () => { - if (!carouselRef.current) { - setCanScrollLeft(false); - setCanScrollRight(false); - return; - } - - const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current; - const isAtStart = scrollLeft <= 1; - const isAtEnd = scrollLeft + clientWidth >= scrollWidth - 1; - - setCanScrollLeft(!isAtStart); - setCanScrollRight(!isAtEnd); - }; - - useEffect(() => { - const carousel = carouselRef.current; - if (!carousel) return; - - updateScrollState(); - - carousel.addEventListener("scroll", updateScrollState); - window.addEventListener("resize", updateScrollState); - - return () => { - carousel.removeEventListener("scroll", updateScrollState); - window.removeEventListener("resize", updateScrollState); - }; - }, []); - const handleScroll = (direction: "left" | "right") => { if (!carouselRef.current) return; @@ -563,17 +530,15 @@ export function EpisodeCarousel({ {/* Episodes Carousel */}
{/* Left scroll button */} - {canScrollLeft && ( -
- -
- )} +
+ +
{/* Right scroll button */} - {canScrollRight && ( -
- -
- )} +
+ +
); diff --git a/src/components/player/atoms/Episodes.tsx b/src/components/player/atoms/Episodes.tsx index 8b9bf424..2d081980 100644 --- a/src/components/player/atoms/Episodes.tsx +++ b/src/components/player/atoms/Episodes.tsx @@ -766,39 +766,6 @@ export function EpisodesView({ ], ); - const [canScrollLeft, setCanScrollLeft] = useState(false); - const [canScrollRight, setCanScrollRight] = useState(false); - - const updateScrollState = () => { - if (!carouselRef.current) { - setCanScrollLeft(false); - setCanScrollRight(false); - return; - } - - const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current; - const isAtStart = scrollLeft <= 1; - const isAtEnd = scrollLeft + clientWidth >= scrollWidth - 1; - - setCanScrollLeft(!isAtStart); - setCanScrollRight(!isAtEnd); - }; - - useEffect(() => { - const carousel = carouselRef.current; - if (!carousel) return; - - updateScrollState(); - - carousel.addEventListener("scroll", updateScrollState); - window.addEventListener("resize", updateScrollState); - - return () => { - carousel.removeEventListener("scroll", updateScrollState); - window.removeEventListener("resize", updateScrollState); - }; - }, []); - const handleScroll = (direction: "left" | "right") => { if (!carouselRef.current) return; @@ -949,22 +916,20 @@ export function EpisodesView({ content = (
{/* Horizontal scroll buttons */} - {canScrollLeft && ( -
+ -
- )} + + +
{/* Right scroll button */} - {canScrollRight && ( -
+ -
- )} + + +
); } diff --git a/src/components/player/base/SubtitleView.tsx b/src/components/player/base/SubtitleView.tsx index aadc31bb..b526806a 100644 --- a/src/components/player/base/SubtitleView.tsx +++ b/src/components/player/base/SubtitleView.tsx @@ -8,6 +8,7 @@ import { } from "@/components/player/utils/captions"; import { Transition } from "@/components/utils/Transition"; import { usePlayerStore } from "@/stores/player/store"; +import { usePreferencesStore } from "@/stores/preferences"; import { SubtitleStyling, useSubtitleStore } from "@/stores/subtitles"; const wordOverrides: Record = { @@ -151,12 +152,17 @@ export function SubtitleRenderer() { export function SubtitleView(props: { controlsShown: boolean }) { const caption = usePlayerStore((s) => s.caption.selected); - const captionAsTrack = usePlayerStore((s) => s.caption.asTrack); + const source = usePlayerStore((s) => s.source); const display = usePlayerStore((s) => s.display); const isCasting = display?.getType() === "casting"; const styling = useSubtitleStore((s) => s.styling); + const enableNativeSubtitles = usePreferencesStore( + (s) => s.enableNativeSubtitles, + ); - if (captionAsTrack || !caption || isCasting) return null; + // Hide custom captions when native subtitles are enabled + const shouldUseNativeTrack = enableNativeSubtitles && source !== null; + if (shouldUseNativeTrack || !caption || isCasting) return null; return ( diff --git a/src/components/player/internals/VideoContainer.tsx b/src/components/player/internals/VideoContainer.tsx index 89d34433..87dec420 100644 --- a/src/components/player/internals/VideoContainer.tsx +++ b/src/components/player/internals/VideoContainer.tsx @@ -4,6 +4,7 @@ import { makeVideoElementDisplayInterface } from "@/components/player/display/ba import { convertSubtitlesToObjectUrl } from "@/components/player/utils/captions"; import { playerStatus } from "@/stores/player/slices/source"; import { usePlayerStore } from "@/stores/player/store"; +import { usePreferencesStore } from "@/stores/preferences"; import { useInitializeSource } from "../hooks/useInitializePlayer"; @@ -66,13 +67,19 @@ function VideoElement() { const trackEl = useRef(null); const display = usePlayerStore((s) => s.display); const srtData = usePlayerStore((s) => s.caption.selected?.srtData); - const captionAsTrack = usePlayerStore((s) => s.caption.asTrack); const language = usePlayerStore((s) => s.caption.selected?.language); + const source = usePlayerStore((s) => s.source); + const enableNativeSubtitles = usePreferencesStore( + (s) => s.enableNativeSubtitles, + ); const trackObjectUrl = useObjectUrl( () => (srtData ? convertSubtitlesToObjectUrl(srtData) : null), [srtData], ); + // Use native tracks when the setting is enabled + const shouldUseNativeTrack = enableNativeSubtitles && source !== null; + // report video element to display interface useEffect(() => { if (display && videoEl.current) { @@ -80,17 +87,20 @@ function VideoElement() { } }, [display, videoEl]); - // select track as showing if it exists + // Control track visibility based on setting useEffect(() => { if (trackEl.current) { - trackEl.current.track.mode = "showing"; + trackEl.current.track.mode = shouldUseNativeTrack ? "showing" : "hidden"; } - }, [trackEl]); + }, [shouldUseNativeTrack, trackEl]); + // Attach track when native subtitles are enabled + // SubtitleView handles showing custom captions when native subtitles are disabled let subtitleTrack: ReactNode = null; - if (captionAsTrack && trackObjectUrl && language) + if (shouldUseNativeTrack && trackObjectUrl && language) { subtitleTrack = ( ); + } return (